SQL Server - суммировать даты по флагу - PullRequest
0 голосов
/ 06 июня 2018

Я использую SQL Server 2008 (хотя при необходимости имею доступ к SQL 2017) и имею такую ​​таблицу:

DECLARE @tbl TABLE (recdate DATE, myflag BIT)

В этой таблице есть строки для всех дат в диапазоне, бит myflagбудет меняться время от времени, что-то вроде этого:

recdate    | myflag
2017-01-01 | 1
2017-01-02 | 1
2017-01-03 | 1
...
2017-04-03 | 1
2017-04-04 | 0
2017-04-05 | 0
..
2017-05-15 | 0
2017-05-16 | 1
etc.

, но мне действительно нужно получить что-то вроде

period_from | period_to  | myflag
2017-01-01  | 2017-04-03 | 1
2017-04-04  | 2017-05-15 | 0
2017-05-16  | 2017-05-21 | 1

, поэтому каждый раз, когда изменяется myflag, он создает новую строкуи в предыдущей строке установлена ​​дата окончания (если это имеет смысл)

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

1 Ответ

0 голосов
/ 06 июня 2018

Это проблема пробелов и островков.Для этой цели вы можете использовать разницу номеров строк:

select min(recdate) as period_from, max(recdate) as period_to, flag
from (select t.*,
             row_number() over (order by recdate) as seqnum,
             row_number() over (partition by flag order by recdate) as seqnum_f
      from @tbl t
     ) t
group by (seqnum - seqnum_f), flag;

Почему это немного сложно объяснить словами.Я обнаружил, что если вы запустите подзапрос, вы поймете, почему разница постоянна для групп, которые вы ищете.

Если ваши даты последовательны без пробелов, дубликатов или временных компонентов, вы можете выполнитьнемного проще:

select min(recdate) as period_from, max(recdate) as period_to, flag
from (select t.*,
             dateadd(day, 
                     - row_number() over (partition by flag order by recdate
                     recdate
                    ) as grp
      from @tbl t
     ) t
group by grp, flag;

Это в основном та же логика, что и в первой версии.

...