只有一个日期列和重复条件的 SQL 岛

Posted

技术标签:

【中文标题】只有一个日期列和重复条件的 SQL 岛【英文标题】:SQL Island with just one date column and duplicated criteria 【发布时间】:2021-08-05 09:55:11 【问题描述】:

我来寻求帮助,我一直在尝试为记录数据集生成孤岛,但我无法做到,我尝试过使用 Lag 函数之类的东西,在每条记录上生成行,然后生成岛屿,但没有得到正确的结果。

我尝试过的解决方案参考:Show Date Range in Custom Column - Gaps and Islands

我需要生成这个数据结构:

 | ChartShiftWeekdayDetailId | IslandStartsOn | IslandEndsOn | NoLinkingReason |
 |          3600             |   2021-06-25   |   2021-07-01 | 'Can't be .....'|
 |          3600             |   2021-07-02   |   2021-07-14 |       null      |
 |          3600             |   2021-07-15   |   2021-07-31 | 'Can't be .....'|
 |          3600             |   2021-08-01   |   2021-08-05 |       null      |

这是一个应该产生预期结果的记录示例。

我已经达到了这个结果

但正如您所见,这不是预期的结果。

这是我尝试过的:

SELECT *,
       CONCAT(NoLinkingReason,
              CAST(DATEDIFF(DAY,
                            LAG(DateValue, 1, CAST(ClearedData.DateValue AS datetime) - 1) OVER (PARTITION BY ChartShiftWeekdayDetailId,
                                                                                                              NoLinkingReason
                                                                                                 ORDER BY DateValue),
                            DateValue) AS varchar(10))) AS NumDays
FROM ClearedData;

非常感谢您的帮助。

【问题讨论】:

那么您尝试了什么,为什么没有成功?您引用了一个不同的问题,而该问题的答案似乎正是您想要的。 嗨@Larnu 当然,我已经尝试使用 Lag 函数作为引用的链接,但我得到的结果非常接近正确,但如果你能看到,第一行从 2021-06-10 到 2021-07-31,这是不正确的,因为中间还有另一个岛,从 2021-07-02 到 2021-07-14。 使用edit 功能。 根据问题指南,请不要发布代码、数据、错误消息等的图像 - 将文本复制或键入问题中。请保留将图像用于图表或演示渲染错误,无法通过文本准确描述的事情。 【参考方案1】:

查看链接和其他答案后,显然没有正确定义差距。这个答案使用了我编造的一些数据。你可以试试这样的

with 
gaps_cte as (
    select *, case when lag(NoLinkingReason, 1, NoLinkingReason) 
                            over (partition by ChartShiftWeekdayDetailId order by DateValue)<>NoLinkingReason then 1 
                   when lag(NoLinkingReason, 1, NoLinkingReason) 
                            over (partition by ChartShiftWeekdayDetailId order by DateValue) is null and NoLinkingReason is not null then 1
                   when lag(NoLinkingReason, 1, NoLinkingReason) 
                            over (partition by ChartShiftWeekdayDetailId order by DateValue) is not null and NoLinkingReason is null then 1
                   else 0 end gap
    from (values (3600, cast('2021-06-25' as date), 'Something'),
                 (3600, cast('2021-06-26' as date), 'Something'),
                 (3600, cast('2021-06-27' as date), 'Nothing'),
                 (3600, cast('2021-06-28' as date), 'Nothing'),
                 (3600, cast('2021-06-29' as date), null),
                 (3600, cast('2021-06-30' as date), Null),
                 (3600, cast('2021-07-01' as date), 'Something'),
                 (3600, cast('2021-07-02' as date), 'Something')
                  ) v(ChartShiftWeekdayDetailId, DateValue, NoLinkingReason)),
grps_cte as (
    select *, sum(gap) over (partition by ChartShiftWeekdayDetailId order by DateValue) grp
    from gaps_cte)
select ChartShiftWeekdayDetailId, 
       min(DateVAlue) IslandStartsOn,
       max(DateVAlue) IslandEndsOn,
       max(NoLinkingReason) NoLinkingReason
from grps_cte
group by ChartShiftWeekdayDetailId, grp
order by min(DateVAlue);
ChartShiftWeekdayDetailId   IslandStartsOn  IslandEndsOn    NoLinkingReason
3600                        2021-06-25      2021-06-26      Something
3600                        2021-06-27      2021-06-28      Nothing
3600                        2021-06-29      2021-06-30      NULL
3600                        2021-07-01      2021-07-02      Something

【讨论】:

真棒@SteveC。我得到了你的样本并在我的查询中实现了它,它工作得很好。谢谢。【参考方案2】:

假设您每天都有数据(如示例数据中所示),您可以从日期中减去一个枚举值并获得特定组的常数。对于每个链接原因,枚举都是分开的:

select ChartShiftWeekdayDetailId, NoLinkingReason,
       min(datevalue), max(datevalue)
from (select cd.*,
             row_number() over (partition by ChartShiftWeekdayDetailId, NoLinkingReason order by datevalue) as seqnum
      from ClearedData cd
     ) cd
group by datediff(day, -seqnum, datevalue)

【讨论】:

以上是关于只有一个日期列和重复条件的 SQL 岛的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server:结合日期列和时间列,插入到日期时间列

如何组合日期列和时间列[重复]

在数据框的其他列上使用多个日期列和条件注释热图

SQL 根据特定列和日期汇总小计

SQL选择不同的列和最新日期

sql查询计算不同列和相邻行的两个日期之间的差异