SQL: запрос таблицы с одной датой с таблицей ежедневных флагов - PullRequest
0 голосов
/ 26 сентября 2018

У меня есть две таблицы, как показано ниже - в одной таблице есть строка для каждого идентификатора и дата, когда произошло определенное событие (или ноль, если событие еще не произошло);в другой таблице есть строка для каждой даты, когда для каждого идентификатора был помечен флаг предупреждения «Y», если флаг не был помечен, для этого идентификатора и даты нет строки:

(обратите внимание на формат даты в Великобритании)

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  First Warning Date
1   01/09/2018
4   06/09/2018

ID2 не имеет даты события;ID3 не имеет флага предупреждения за день до даты его события;а в ID4 есть две строки флагов предупреждений, но должна учитываться только самая последняя строка.

У меня нет идеи, даже как начать, любые указатели?

Вы бы переставили какую-либо изТаблицы / построить сводную таблицу перед попыткой построить запрос, или все это можно сделать одним запросом?

[это в конечном итоге будет закодировано кем-то другим в Oracle или HiveQL, но я хочу понять запрослогика до того, как это зашло так далеко, как они все равно спросят меня :)]

1 Ответ

0 голосов
/ 26 сентября 2018

Это вариант проблемы групп и островов.Вы можете начать с разделения предупреждений на диапазоны.

Обратите внимание, что арифметика даты специфична для баз данных, поэтому точный синтаксис зависит от базы данных.Но вот идея:

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;

Я должен подчеркнуть, что это по сути псевдо-код, потому что функции даты должны быть настроены для любой используемой вами базы данных.

...