google-bigquery - 将一组变量和值与最近的日期时间匹配
问题描述
我有一个transaction
看起来像这样的表:
transaction_start store_no item_no amount post_voided
2021-03-01 10:00:00 001 101 45 N
2021-03-01 10:00:00 001 105 25 N
2021-03-01 10:00:00 001 109 40 N
2021-03-01 10:05:00 002 103 35 N
2021-03-01 10:05:00 002 135 20 N
2021-03-01 10:08:00 001 140 2 N
2021-03-01 10:11:00 001 101 -45 Y
2021-03-01 10:11:00 001 105 -25 Y
2021-03-01 10:11:00 001 109 -40 Y
该表没有 id 列;给transaction_start
定store_no
的永远不会相同。
每当交易被取消后,交易就会以相同的 重复store_no
,item_no
但带有负/负amount
和等于或更高的transaction_start
。此外,该列post_voided
等于“Y”。
在上面的示例中,行 1-3 具有相同的transaction_start
和store_no
,因此属于同一收据,包含三个不同的项目(101、105、109)。相同的逻辑适用于其他行:第 4-5 行属于同一收据,依此类推。在示例中,可以看到 4 个不同的收据。最后三行给出的最后一个收据是与第一个收据(第 1-3 行)无效的帖子。
我想要做的是transaction_start
将post_voided
= 'Y' 交易(在我的示例中,只有一个收据 - 由最后三行表示 - 有它)更改为具有变量的类似收据的下一个/最近的日期时间store_no
,item_no
和 (negative) amount
(but post_voided
= 'N') (在我的示例中,前三行给出了类似的票证 - store_no
,所有item_no
和(正)amount
匹配)。transaction_start
邮局作废收据总是等于或高于“原始”收据。
期望的输出:
transaction_start store_no item_no amount post_voided
2021-03-01 10:00:00 001 101 45 N
2021-03-01 10:00:00 001 105 25 N
2021-03-01 10:00:00 001 109 40 N
2021-03-01 10:05:00 002 103 35 N
2021-03-01 10:05:00 002 135 20 N
2021-03-01 10:08:00 001 140 2 N
2021-03-01 10:00:00 001 101 -45 Y
2021-03-01 10:00:00 001 105 -25 Y
2021-03-01 10:00:00 001 109 -40 Y
这里是表格的链接:https ://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=26142fa24e46acb4213b96c86f4eb94b
提前致谢!
解决方案
考虑下面
select a.* replace(ifnull(b.transaction_start, a.transaction_start) as transaction_start)
from `project.dataset.table` a
left join (
select * replace(-amount as amount)
from `project.dataset.table`
where post_voided = 'N'
) b
using (store_no, item_no)
如果应用于您问题中的样本数据 - 输出是
考虑下面的新/扩展示例(https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=91f9f180fd672e7c357aa48d18ced5fd)
select x.* replace(ifnull(y.original_transaction_start, x.transaction_start) as transaction_start)
from `project.dataset.table` x
left join (
select b.transaction_start, b.store_no, b.item_no, b.amount amount,
max(a.transaction_start) original_transaction_start
from `project.dataset.table` a
join `project.dataset.table` b
on a.store_no = b.store_no
and a.item_no = b.item_no
and a.amount = -b.amount
and a.post_voided = 'N'
and b.post_voided = 'Y'
and a.transaction_start < b.transaction_start
group by b.transaction_start, b.store_no, b.item_no, b.amount
) y
using (store_no, item_no, amount, transaction_start)
带输出
推荐阅读
- javascript - D3.js:实时旭日形分区数据:重新创建层次结构?
- python - 我如何使用正则表达式从 cloudwatchloginsights 查询的输出中过滤?
- forms - Shopify Liquid 联系表发送到多个电子邮件
- excel - 如何在 excel VBA 中使用旧的对象库版本?
- javascript - javascript中“super”关键字的复杂性
- oracle - PLSQL: CLOB 数据返回 ORA:06502
- java - 你能帮忙解决这个问题吗,为什么它不在运行线程中求和?
- ios - 使嵌入 Storyboard ViewController 的 SwiftUI 视图使用全屏宽度
- java - 有没有办法在java中检查优先级队列中的优先级?
- python - 当主窗口不可见时隐藏或关闭 Tkinter 顶级窗口