【问题标题】:SQL Server - Calculate Time Between Rows With Some ConditionsSQL Server - 在某些条件下计算行之间的时间
【发布时间】:2021-04-03 00:08:51
【问题描述】:


我想计算多行之间的时间基于:

  1. 第一名:姓名
  2. 2nd:事件类型 - 事件本身有条件,因为计算应适用于 24 小时。

条件:

如果第一个事件是“不可用”,则时间应从 00:00:00 到事件发生时间计算。 否则时间将根据“可用”与下一个“不可用”或“可用”之间的差异计算。 如果最后一个活动是“可用”,时间将从活动时间开始计算到 23:59:59

毕竟,计算的时间总和与一些其他信息应该插入到另一个表中。

表格如下所示:

ID Name Type Date-Time
1 X1 Not Available 2021-03-30 04:12:00
2 X1 Available 2021-03-30 08:12:00
3 X1 Available 2021-03-30 10:12:00
4 X1 Not Available 2021-03-30 11:32:00
5 X1 Available 2021-03-30 20:30:00
6 X2 Available 2021-03-30 08:30:00
7 X2 Not Available 2021-03-30 18:12:00

【问题讨论】:

  • 请详细说明并提供所需的输出 - “第一”意味着什么 - 是按 ID 排序的吗?
  • “first”和“last”是否应该按名称分组?时间计算是否会跨越到不同的日子,还是会一直局限于同一天?
  • 在您努力提供结果应该是什么样子时,请查看 LEAD() 和 LAG()
  • @Stu 不是按 ID 排序的,我把 ID 字段用于制作样品,但它是按名称排序的。
  • @jw11432 从 00:00:00 到 23:59:59,他们总是在同一天。是的,他们应该按“名称”分组

标签: sql-server


【解决方案1】:

这就是我得到的似乎有效的东西。仔细检查没有丢失的逻辑。

create table #test (ID int, Name varchar(4),    Type varchar(20),   DateTime datetime)

insert into #test values
('1',   'X1',   'Not Available',    '2021-03-30 04:12:00'),
('2',   'X1',   'Available',    '2021-03-30 08:12:00'),
('3',   'X1',   'Available',    '2021-03-30 10:12:00'),
('4',   'X1',   'Not Available',    '2021-03-30 11:32:00'),
('5',   'X1',   'Available',    '2021-03-30 20:30:00'),
('6',   'X2',   'Available',    '2021-03-30 08:30:00'),
('7',   'X2',   'Not Available',    '2021-03-30 18:12:00')



WITH CTE
 AS (SELECT *
          , Time = CAST(datetime AS TIME(0))
          , NextTime = LEAD(CAST(datetime AS TIME(0))) OVER(
            ORDER BY id)
          , RN = ROW_NUMBER() OVER(PARTITION BY name
            ORDER BY id)
     FROM #test),
 CTE2
 AS (SELECT *
          , first = CASE
                        WHEN RN = 1
                             AND type = 'Not Available' THEN CAST(Time AS TIME(0))
                    END
          , second = CAST(DATEADD(ms, DATEDIFF(second, datetime, LEAD(datetime) OVER(PARTITION BY name
                                      ORDER BY datetime)) * 1000, 0) AS TIME(0))
     FROM cte),
 CTE3
 AS (SELECT id
          , name
          , type
          , datetime
          , TimeDiff = ISNULL(first, second)
     FROM cte2),
 CTE4
 AS (SELECT name
          , TimeSum = CAST(DATEADD(ms, SUM(DATEDIFF(ms, '00:00:00.000', TimeDiff)), '00:00:00.000') AS TIME(0))
     FROM cte3
     WHERE type = 'available'
     GROUP BY name)
 SELECT cte3.*
      , cte4.TimeSum
 FROM cte4
      JOIN cte3 ON cte4.name = cte3.name

【讨论】:

  • 谢谢,它似乎工作。如何将每个名称的时间差总和作为一条记录并将其插入另一个表?
  • 请告诉我,我如何计算“可用”类型的单条记录的时间。不是计算出来的。
  • 修改为对时间求和。如果它适合你,请接受我的绿色复选标记。
  • 谢谢,但有两个问题,如果我有“可用”类型的单条记录,则不计算时间。另一个问题,最后一条记录有时间总和(持续时间),但新查询将对所有其他记录求和。所以总时间是错误的。
  • 你显然需要调整它。我已经为你完成了 95% 的工作,所以这是一个很好的开始。你的描述没有给出一个全面的需求列表,所以我尽我所能用你提供的东西。
猜你喜欢
  • 2022-08-18
  • 1970-01-01
  • 1970-01-01
  • 2017-07-03
  • 2020-07-03
  • 1970-01-01
  • 1970-01-01
  • 2019-12-25
  • 1970-01-01
相关资源
最近更新 更多