SQL:使用日标表查询单日期表

时间:2018-09-26 15:04:48

标签: sql date flags

我下面有两个表-一个表的每个ID都有一行,以及特定事件发生的日期(如果尚未发生该事件,则为null);另一个表在每个日期的每一行都有一个行,其中每个ID的警告标志都标记为“ Y”,如果未标记该标志,则该ID和日期没有行:

(请注意英国日期格式)

ID    Event Date
1     04/09/2018
2     null
3     05/09/2018
4     07/09/2018

ID    Date         Warning Flag
1     01/09/2018   Y
1     02/09/2018   Y
1     03/09/2018   Y
2     01/09/2018   Y
2     02/09/2018   Y
2     03/09/2018   Y
3     01/09/2018   Y
3     02/09/2018   Y
3     03/09/2018   Y
4     01/09/2018   Y
4     02/09/2018   Y
4     06/09/2018   Y

我想选择任何事件日期在事件日期前一天标记有警告标志的ID,以及警告标志字符串开始的日期。所以

ID  First Warning Date
1   01/09/2018
4   06/09/2018

ID2没有活动日期; ID3在事件发生日期的前一天没有警告标志;和ID4有两个警告标志字符串,但仅应计算最近的字符串。

我什至不知道如何启动它,任何指针?

在尝试构建查询之前,您会重新排列任何表/构建汇总表吗?还是可以在单个查询中完成所有操作?

[这最终将由Oracle或HiveQL中的其他人编码,但我想在查询逻辑深入了解查询逻辑之前,因为他们无论如何都会问我:)]

1 个答案:

答案 0 :(得分:1)

这是关于群体和岛屿问题的变体。您可以先将警告划分为多个范围。

请注意,日期算术特定于数据库,因此确切的语法因数据库而异。但这就是这个想法:

select min(date) as mindate, max(date) as maxdate
from (select df.*, row_number() over (partition by id order by date) as seqnum
      from dailyflag df
     ) df
group by date - seqnum * interval '1 day';

接下来,将其用于join,然后使用一些日期算术得出结果:

select e.*,
       (e.event_date - df.mindate + 1) as numdays
from events e join
     (select min(date) as mindate, max(date) as maxdate
      from (select df.*, row_number() over (partition by id order by date) as seqnum
            from dailyflag df
           ) df
      group by date - seqnum * interval '1 day'
     ) df
     on e.event_date - interval '1 day' between df.mindate and df.maxdate;

我必须强调,这本质上是伪代码,因为日期函数需要针对您使用的任何数据库进行自定义。