【问题标题】:Overnight Rules Query隔夜规则查询
【发布时间】:2021-03-25 20:50:27
【问题描述】:

我有数据:

Current Data

StartDate StartTime EndDate EndTime
12/10/2020 09:00:00 12/13/2020 12:00:00

我想要如下输出:

Output Data

StartDate StartTime EndDate EndTime Duration
12/10/2020 09:00:00 12/10/2020 23:59:59 14:59:59
12/11/2020 00:00:00 12/11/2020 23:59:59 23:59:59
12/12/2020 00:00:00 12/12/2020 23:59:59 23:59:59
12/13/2020 00:00:00 12/13/2020 12:00:00 12:00:00

在 T-SQL 中怎么可能?我正在运行 SQL Server 14.x 版本。

我的尝试:

 With cte as(

            Select [Start Date] StartDate ,
            Case
                When [Start Date] = [End Date] Then Duration
                When [Start Date] != [End Date] Then  DateDiff(MINUTE,[Start Time],'23:59:59')
            End
                as ShutdownTime
                 from [dbo].[Delay]
                 where 
                    [Start Date]>=@StartDate and [Start Date]<= @EndDate                        
        Union 

            Select [End Date] StartDate, 
             DateDiff(Minute,'00:00:00', [End Time])
            as ShutdownTime
                 from [dbo].[Delay]
                 where  [Start Date] !=[End Date]
                 and
                    [Start Date]>=@StartDate and [Start Date]<= @EndDate                    
                    
                    
        )
    Select StartDate, Sum(ShutDownTime/cast(60 as float)) ShutDownTime
    from cte group by StartDate

如果少于 24 小时。它工作正常。但如果超过 24 小时,它就会失败。

【问题讨论】:

  • 请不要将图像用于代码、数据或错误。使用格式化文本。请向我们展示您的尝试并解释您遇到的问题/
  • 如果您阅读过Markdown help,那么您可以创建一个更好(看起来)的问题。现在你只需要提供一些关于你的尝试的信息并解释你的问题所在(就像戴尔问的那样)
  • 我已经提供了我的尝试以及失败的原因
  • 请解释持续时间的计算。
  • 哎呀,我确实在将图片过度输入到文本时出错了......这导致了一些关于持续时间的问题......我现在会更正这个!

标签: sql sql-server tsql


【解决方案1】:

首先,使用日期/时间比将它们放在单独的列中要简单得多。

其次,您需要递归 CTE。这是工作代码:

with cte as (
      select convert(datetime, startdate) + convert(datetime, starttime) as day_startdt,
             (case when t.startdate = t.enddate 
                   then v.enddt else dateadd(day, 1, t.startdate)
              end) as day_enddt,
             v.enddt, 1 as lev
      from t cross apply
           (values (convert(datetime, enddate) + convert(datetime, endtime))) v(enddt)
      union all
      select cte.day_enddt,
             (case when cte.day_enddt < convert(date, cte.enddt)
                   then dateadd(day, 1, cte.day_enddt) else cte.enddt 
              end) as day_enddt,
             cte.enddt, lev + 1
      from cte
      where cte.day_startdt < dateadd(day, -1, cte.enddt)
     )
select *
from cte;

Here 是一个 dbfiddle。

请注意,这包括全天,这对我来说很有意义。它不计算持续时间,因为该计算在问题中看起来不正确 - 如果是,您需要解释它。

如果需要,您可以轻松地将其拆分为单独的 date/time 列,尽管我不建议这样做。

【讨论】:

    【解决方案2】:

    我建议创建一个带有计算列的视图:

    CREATE VIEW [schema_name.]view_name 
    AS SELECT
        StartDate, StartTime, EndDate, EndTime, 
        DATEDIFF(hour, StartTime, EndTime) + ':' +
        DATEDIFF(minute, StartTime, EndTime) + ':' +
        DATEDIFF(second, StartTime, EndTime) + ':' AS 'Duration'
    FROM [schema_name.]table_name;  
    

    链接:

    如果您的日期/时间不是 DATETIME 类型(或类似类型),请查看 CAST and CONVERT

    【讨论】:

      【解决方案3】:
      DECLARE @StartDate DATE = '2020-10-12';
      DECLARE @StartTime TIME = '09:00:00';
      DECLARE @EndDate   DATE = '2020-12-12';
      DECLARE @EndTime   TIME = '12:00:00';
      
      WITH cte as (
        select 
          @StartDate as StartDate,
          @StartTime as StartTime,
          CASE WHEN @StartDate<>@EndDate THEN @StartDate ELSE @EndDate END as EndDate,
          CASE WHEN @StartDate<>@EndDate THEN CAST('23:59:59' AS TIME) ELSE @EndTime END as EndTime
        union all
        select 
          DATEADD(day,1,StartDate),
          StartTime,
          DATEADD(day,1,EndDate),
          CASE WHEN EndDate<>@EndDate THEN CAST('23:59:59' AS TIME) ELSE @EndTime END as EndTime
        from cte
        where EndDate <= @EndDate
        )
        select 
           StartDate,
           StartTime,
           EndDate,
           EndTime,
           CONVERT(TIME,DATEADD(second, DATEDIFF(second,StartTime,EndTime),0)) as Duration
        from cte;
      

      持续时间计算为StartTime 和EndTime 之间的差异,因为将值存储在仅依赖于其他字段(在同一个表中)的数据库中并不是明智之举。

      【讨论】:

        猜你喜欢
        • 2020-01-28
        • 1970-01-01
        • 1970-01-01
        • 2012-10-01
        • 2014-04-25
        • 2020-05-16
        • 2017-11-06
        • 1970-01-01
        • 2017-01-28
        相关资源
        最近更新 更多