是否有窗口函数或窗口函数组合可用于通过 TSQL 获得所需的结果
Posted
技术标签:
【中文标题】是否有窗口函数或窗口函数组合可用于通过 TSQL 获得所需的结果【英文标题】:Is there a window function or combination of window functions that I can use to get this desired result via TSQL 【发布时间】:2020-05-25 19:32:03 【问题描述】:以下表为例:
ORDER_KEY | STATUS_DATE | TASK_CREATED_DATE | TASK_KEY | TASK_ROW_ID | TASK_REVISION_ID
-----------|-----------------|-------------------|------------|-------------|------------------
1274796898 | 10/4/2019 18:19 | 10/4/2019 18:12 | 5277852673 | 1 |
1274796898 | 10/4/2019 18:19 | 10/4/2019 18:12 | 5277852674 | 2 |
1274796898 | 10/4/2019 18:19 | 4/7/2020 14:22 | 5277853673 | 3 | 1
1274796898 | 10/4/2019 18:19 | 4/7/2020 14:22 | 5277853674 | 4 | 1
1274796898 | 10/4/2019 18:19 | 4/7/2020 14:22 | 5277853675 | 5 | 1
1274737653 | 10/4/2019 15:32 | 10/4/2019 15:31 | 5277852586 | 1 |
1274737653 | 10/4/2019 15:32 | 10/4/2019 15:31 | 5277852587 | 2 |
1274737653 | 10/4/2019 15:32 | 10/4/2019 15:31 | 5277852588 | 3 |
1274737653 | 10/4/2019 15:32 | 10/4/2019 15:32 | 5277852589 | 4 |
1274737647 | 10/4/2019 11:49 | 10/4/2019 11:42 | 5277855586 | 1 |
1274737647 | 10/4/2019 11:49 | 10/4/2019 11:42 | 5277855587 | 2 |
1274737647 | 10/4/2019 11:49 | 10/4/2019 11:42 | 5277855588 | 3 |
1274737647 | 10/4/2019 11:49 | 10/4/2019 11:42 | 5277855589 | 4 |
1274737647 | 10/4/2019 11:49 | 10/4/2019 11:42 | 5277855590 | 5 |
1274737647 | 10/4/2019 11:49 | 10/4/2019 11:49 | 5277855587 | 6 |
1274737647 | 10/4/2019 11:49 | 10/4/2019 11:49 | 5277856270 | 7 |
1274737647 | 10/4/2019 11:49 | 4/7/2020 14:10 | 5281403575 | 8 | 1
1274737647 | 10/4/2019 11:49 | 4/7/2020 14:10 | 5281403576 | 9 | 1
1274737647 | 10/4/2019 11:49 | 4/7/2020 14:12 | 5281403595 | 10 | 1
1274737647 | 10/4/2019 11:49 | 4/14/2020 09:32 | 5281403599 | 11 | 2
1274737647 | 10/4/2019 11:49 | 4/26/2020 13:10 | 5281403600 | 12 | 3
可以通过以下查询重现:
with data as (
select *
from (
values
(1274796898, '10/4/2019 18:19', '10/4/2019 18:12', 5277852673, 1),
(1274796898, '10/4/2019 18:19', '10/4/2019 18:12', 5277852674, 2),
(1274796898, '10/4/2019 18:19', '4/7/2020 14:22', 5277853673, 3),
(1274796898, '10/4/2019 18:19', '4/7/2020 14:22', 5277853674, 4),
(1274796898, '10/4/2019 18:19', '4/7/2020 14:22', 5277853675, 5),
(1274737653, '10/4/2019 15:32', '10/4/2019 15:31', 5277852586, 1),
(1274737653, '10/4/2019 15:32', '10/4/2019 15:31', 5277852587, 2),
(1274737653, '10/4/2019 15:32', '10/4/2019 15:31', 5277852588, 3),
(1274737653, '10/4/2019 15:32', '10/4/2019 15:32', 5277852589, 4),
(1274737647, '10/4/2019 11:49', '10/4/2019 11:42', 5277855586, 1),
(1274737647, '10/4/2019 11:49', '10/4/2019 11:42', 5277855587, 2),
(1274737647, '10/4/2019 11:49', '10/4/2019 11:42', 5277855588, 3),
(1274737647, '10/4/2019 11:49', '10/4/2019 11:42', 5277855589, 4),
(1274737647, '10/4/2019 11:49', '10/4/2019 11:42', 5277855590, 5),
(1274737647, '10/4/2019 11:49', '10/4/2019 11:49', 5277855587, 6),
(1274737647, '10/4/2019 11:49', '10/4/2019 11:49', 5277856270, 7),
(1274737647, '10/4/2019 11:49', '4/7/2020 14:10', 5281403575, 8),
(1274737647, '10/4/2019 11:49', '4/7/2020 14:10', 5281403576, 9),
(1274737647, '10/4/2019 11:49', '4/7/2020 14:12', 5281403595, 10),
(1274737647, '10/4/2019 11:49', '4/14/2020 09:32', 5281403599, 11),
(1274737647, '10/4/2019 11:49', '4/26/2020 13:10', 5281403600, 12)
) v (ORDER_KEY, STATUS_DATE, TASK_CREATED_DATE, TASK_KEY, TASK_ROW_ID)
)
select * from data;
我最终希望实现的行为是 TASK_REVISION_ID
列输出。
在上面的数据中,出于说明目的,它是手动输入的。
TASK_ROW_ID = ROW_NUMBER() OVER(PARTITION BY ORDER_KEY ORDER BY TASK_CREATED_DATE, TASK_KEY)
在ORDER_KEY
级别,我想按以下方式增加TASK_REVISION_ID
:
-
当
TASK_CREATED_DATE
> STATUS_DATE
时将TASK_REVISION_ID
设置为1
当当前行 TASK_CREATED_DATE
和前一行 TASK_CREATED_DATE
之间的分钟差值以分钟为单位时增加 TASK_REVISION_ID
>= 5
【问题讨论】:
这些数据对我们来说不是消耗品。请花时间提供 DDL 和 DML 语句,或表格格式的text
。除此之外,您的预期结果是什么?你做了哪些尝试,为什么没有奏效?
我的桌子照片有帮助吗?
Does my table pic assist at all?
- not really。我不会重新输入。
如何嵌入我的表格,同时保持这篇文章的易读性?
通过将数据发布为表格格式 text
或 DDL 和 DML 语句 @DeeRinos ,正如我在第一条评论中提到的那样。
【参考方案1】:
这回答了问题的原始版本。
此查询捕获了您所描述的内容:
select (case when grp = 1
then sum(case when prev_tcd > dateadd(minute, -5, TASK_CREATED_DATE) then 0 else 1 end) over
(partition by d.order_key, v.grp order by task_created_date)
end),
d.*
from (select d.*,
lag(TASK_CREATED_DATE) over (partition by order_key order by TASK_CREATED_DATE) as prev_tcd
from data d
) d cross apply
(values ((case when task_created_date > status_date then 1 else 0 end))) v(grp)
order by 1, 2, 3;
Here 是一个 dbfiddle。
【讨论】:
感谢您的回复,但我正在尝试从包含的 ASCII 表插图中输出相同的“TASK_REVISION_ID”输出。上述 SQL 解决方案会产生不同的结果。 我说得太早了。非常感谢 Gordon :) 这正是我在将所有日期字段转换为 DATE 后所寻找的结果 嗨,戈登,关于这个附加场景的任何想法,为什么它会为 task_revision_id 产生 0 而不是 1? @DeeRinos 。 . .您能否提出一个新问题,并提供适当的示例数据和解释? 它需要是 TASK_CREATED_DATE > STATUS_DATE,在新示例中我包含的 TASK_CREATED_DATE (1/10/2017 12:42) 大于 STATUS_DATE (1/10/2017 12:41) 但它给出最终是 0 而不是 1?【参考方案2】:你只需要稍微修改一下original answer就显示出正确的想法:
select
d.ORDER_KEY, d.STATUS_DATE, d.TASK_CREATED_DATE, d.TASK_KEY, d.TASK_ROW_ID,
task_revision_id = (
case when grp = 1
then sum(case when datediff(mi, prev_tcd, TASK_CREATED_DATE) > 5 or grp_first = 1 then 1 else 0 end) over
(partition by d.order_key, d.grp order by task_row_id)
end
)
from
(select d.*,
lag(TASK_CREATED_DATE) over (partition by order_key order by task_row_id) as prev_tcd,
case when task_created_date > status_date then 1 else 0 end as grp,
case when lag(case when task_created_date > status_date then 1 else 0 end, 1, 0) over (partition by order_key order by task_row_id) = 0 then 1 else 0 end as grp_first
from
data d
) d
order by
order_key,
task_row_id
【讨论】:
非常感谢GSerg。您的 Gordon 提供的原始解决方案版本成功了。感谢你们两位帮助我解决我的问题。继续努力!!!以上是关于是否有窗口函数或窗口函数组合可用于通过 TSQL 获得所需的结果的主要内容,如果未能解决你的问题,请参考以下文章
无论窗口时间如何,都可以在Apache Flink中组合两个流