【问题标题】:Sql split entries into two entries if EndDateTime is the next day(after midnight)如果 EndDateTime 是第二天(午夜之后),则 Sql 将条目拆分为两个条目
【发布时间】:2020-04-23 10:53:02
【问题描述】:

我有这个问题:

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

如果记录跨越一天以上。什么都不需要做。最终解决方案应该能够为历史表工作。 超过 300 万行

所以记录应该是这样的

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

我希望这是有道理的!

所有其他记录都会产生类似的结果。有些记录不需要拆分。

【问题讨论】:

  • 如果一条记录跨越两天以上怎么办?你用的是什么数据库?请适当标记。
  • 我们可以看到您用于构建查询结果的数据吗?
  • @JMabee 我已经提供了模拟数据。很小。预计其他行也会有类似的结果。你需要更多吗?

标签: sql sql-server date


【解决方案1】:

您问题中的结果集不能是您指定的查询的结果(每个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;

Here 是一个 dbfiddle。

【讨论】:

  • 我仍然收到错误 -> Msg 319, Level 15, State 1, Line 3 Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon. Msg 102, Level 15, State 1, Line 24 Incorrect syntax near ')'.
  • @panoskarajohn 。 . .在它前面加上一个分号。 with 需要开始一个语句,如果在它之前有一个未终止的语句,SQL Server 会感到困惑。
猜你喜欢
  • 2018-10-24
  • 1970-01-01
  • 2017-10-13
  • 2019-12-07
  • 1970-01-01
  • 1970-01-01
  • 2012-10-09
  • 2019-05-29
  • 2016-01-09
相关资源
最近更新 更多