Sql разделить записи на две записи, если EndDateTime следующий день (после полуночи) - PullRequest
1 голос
/ 23 апреля 2020

У меня есть этот запрос:

select 
    sth.Id,
    sth.CreatedDateTime, 
    EndDateTime = Lead(sth.CreatedDateTime, 1) over (partition by sth.Id order by sth.Id, sth.CreatedDateTime)
from 
    Sth as sth
order by 
    sth.Id, sth.CreatedDateTime

, который возвращает эти результаты:

Id        StartDateTime                 EndDate                     
--------------------------------------------------------------------
2746743   2019-11-20 14:35:05.5841266   NULL                         
2746744   2019-11-20 14:35:05.5841266   NULL                         
3         2018-06-25 23:35:12.2799952   2018-06-26 09:57:27.8943163  
13        2018-06-26 09:57:27.8943163   2018-06-26 10:41:19.2973307  

Меня попросили обновить вышеупомянутый запрос, разделить строку с помощью Id=3 на два строки.

Значение: как вы видите запись с Id 3 начинается с 23:35 and ends the **next day** at 09:57

Что мне нужно, чтобы разделить эту запись на две части.

Первая значение должно быть от 23:35 -> 23:59

А нижеприведенное должно быть от 00:00 -> 09:57

Если записи охватывают более одного дня. Ничего не нужно делать. Также конечное решение должно работать для таблицы истории . Более 3 миллионов строк .

Таким образом, запись должна привести к вот так:

Id     StartDateTime                    EndDateTime
3      2018-06-25 23:35:12.2799952      2018-06-25 23:59:59.000000
3      2018-06-26 00:00:00.0000000      2018-06-26 09:57:27.8943163

Надеюсь, это имеет смысл!

Все остальные записи приведут к аналогичным результатам. Есть записи, которые не нужно разбивать.

1 Ответ

1 голос
/ 23 апреля 2020

Результирующий набор в вашем вопросе не может быть результатом указанного вами запроса (каждый id будет иметь значение null для даты окончания). Итак, я интерпретирую вопрос как обработку ситуации, когда присутствует дата окончания и один день после даты начала.

Я бы просто использовал боковое соединение:

with t as (
      select sth.*, CreatedDateTime as StartDateTime,
             Lead(sth.CreatedDateTime, 1) over (partition by sth.Id order by sth.Id, sth.CreatedDateTime) as EndDateTime
      from Sth as sth
     )
select t.id, v.*
from t cross apply
     (values (startdatetime,
               (case when datediff(day, startdatetime, enddatetime) = 1
                     then dateadd(second, -1, dateadd(day, 1, convert(datetime, convert(date, startdatetime))))
                     else enddatetime
                end)
              ),
              (dateadd(day, 1, convert(date, startdatetime)),
               (case when datediff(day, startdatetime, enddatetime) = 1
                     then enddatetime
                end)
              )
     ) v(startdatetime, enddatetime)
where v.enddatetime is not null;

Здесь - это дБ <> скрипка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...