SQL计算较大时间范围内的多个时间差

时间:2018-01-12 12:25:50

标签: sql sql-server date datetime sql-server-2017

我有一个带有跟踪两个日期列的表的sql后端。这两列称为OnTime和OffTime。列的格式为小日期时间。该表由一个带有VB形式应用程序的arduino微控制器填充,当检测到电压时,该应用程序将在OnTime列中插入日期,并在电压被移除时填充OffTime日期。我需要编写一个sql查询,它可以收集每个开关时间戳之间检测到的总时间电压。查询应该类似于

SELECT (get times) FROM tableA WHERE OnTime >= @sometime AND OffTime <= @Sometime.

这将允许我运行关于检测到电压的总分钟的报告。我熟悉使用Datediff()函数获取时间,但我不确定以这种方式汇总多个datediff()

示例数据:

| ID | OnTime           | OffTime          |
|----|------------------|------------------|
| 1  | 2017-01-01 09:36 | null             |
| 2  | null             | 2017-01-01 10:36 |
| 3  | 2017-01-07 05:36 | null             |
| 4  | null             | 2017-01-07 6:36 |

其中Id,ontime和Offtime是列。

期望的结果是总时间为120分钟

4 个答案:

答案 0 :(得分:2)

您可以使用老式的方式组合行:

WITH testdata (ID, OnTime, OffTime) AS (
    SELECT 1, '2017-01-01 09:36', null UNION
    SELECT 2, null, '2017-01-01 10:36' UNION
    SELECT 3, '2017-01-07 05:36', null UNION
    SELECT 4, null, '2017-01-07 6:36'
), on_off_time AS (
    SELECT a.ID, a.OnTime, MIN(b.OffTime) AS OffTime
    FROM testdata a
    INNER JOIN testdata b ON b.OffTime > a.OnTime
    GROUP BY a.ID, a.OnTime
)
SELECT SUM(DATEDIFF(MINUTE, OnTime, OffTime))
FROM on_off_time

或使用LAG函数(SQL Server 2012或更高版本):

WITH testdata (ID, OnTime, OffTime) AS (
    SELECT 1, '2017-01-01 09:36', null UNION
    SELECT 2, null, '2017-01-01 10:36' UNION
    SELECT 3, '2017-01-07 05:36', null UNION
    SELECT 4, null, '2017-01-07 6:36'
), on_off_time AS (
    SELECT ID, LAG(OnTime, 1, NULL) OVER (ORDER BY COALESCE(OnTime, OffTime)) AS OnTime, OffTime
    FROM testdata
)
SELECT SUM(DATEDIFF(MINUTE, OnTime, OffTime))
FROM on_off_time
WHERE OffTime IS NOT NULL

答案 1 :(得分:1)

考虑表

ID | OnTime             | OffTime
---|--------------------|--------------
  1|2018-02-12 08:00:00 |null
  2|null                |2018-02-12 09:00:00
  3|2018-02-13 07:00:00 |null
  4|null                |2018-02-13 09:00:00

您可以执行以下操作:

WITH Ons AS
(
 SELECT ID,
        ID + 1 AS IDPlusOne,
        OnTime
 FROM Dates
 WHERE NOT OnTime IS NULL 
)
,

Offs AS
(
 SELECT ID,
        OffTime
 FROM Dates
 WHERE NOT OffTime IS NULL
)

SELECT Ons.ID, 
       Offs.ID, 
       DateDiff(MINUTE, Ons.OnTime, Offs.OffTime) as DiffInMinutes 
FROM Ons INNER JOIN Offs ON Ons.IDPlusOne = Offs.ID

导致

ID | ID | DiffInMinutes
---|----|---------------
  1|   2|60
  3|   4|120

但是你的设计很不幸,因为它需要记录 严格按顺序排列。我强烈建议在同一记录中保存两个日期时间

答案 2 :(得分:0)

如果您的条目始终与其ID一致,您可以使用这种简单的方法来获取每个数据点之间的时间:

SELECT ID,DATEDIFF(MINUTE, Ontime, (SELECT Offtime FROM yourtable t2 where t2.ID = t.ID+1)) AS 'Minutes on, per period'
FROM yourtable t
WHERE Ontime is not null;

您可以根据需要进行扩展,例如通过这样的总结

 SELECT SUM(Minutes) AS 'Total minutes on, all periods'
    FROM (
      SELECT ID,DATEDIFF(MINUTE, Ontime, (SELECT Offtime FROM yourtable t2 where t2.ID = t.ID+1)) AS 'Minutes'
      FROM yourtable t
      WHERE Ontime is not null
    ) AS Subtable

如果你想尝试这个例子,我在这里做了一个小提琴:http://sqlfiddle.com/#!6/9db41/18

答案 3 :(得分:0)

以下代码对您有所帮助,

transform

点击此处:http://sqlfiddle.com/#!6/1c4bd/3