计算值大于x

时间:2019-02-01 09:49:49

标签: sql sql-server datetime sql-server-2017 gaps-and-islands

我希望能够以分钟为单位计算温度列超过特定温度的总时间。例如,我想知道温度在16分钟以上达到了多长时间。

如果12:28的读数为16,而12:30的读数为17,那么我们说的是从12:2812:30 ,则值为17

此外,如果第一个或唯一读数高于x(17),则将是两分钟,因为启动设备时,需要x分钟(在这种情况下为2分钟)才能进行第一次读数。

  • 序列号是读取温度的设备的序列号。
  • CombinDateTime是获取温度读数的时间。
  • 温度是温度值。

  SerialNumber, CombinDateTime, Temperature
  1000649496, 2018-12-05 10:56:52,    16.6
  1000649496, 2018-12-05 10:58:52,    17.3
  1000649496, 2018-12-05 11:00:52,    16.8
  1000649496, 2018-12-05 11:02:52,    16.6
  1000649496, 2018-12-05 11:04:52,    16.4
  1000649496, 2018-12-05 11:06:52,    16.3
  1000649496, 2018-12-05 11:08:52,    16.3
  1000649496, 2018-12-05 11:10:52,    16.2
  1000649496, 2018-12-05 11:12:52,    16.2
  1000649496, 2018-12-05 11:14:52,    16.2
  1000649496, 2018-12-05 11:16:52,    16.2
  1000649496, 2018-12-05 11:18:52,    16.2
  1000649496, 2018-12-05 11:20:52,    16.1
  1000649496, 2018-12-05 11:22:52,    16.1
  1000649496, 2018-12-05 11:24:52,    16.1
  1000649496, 2018-12-05 11:26:52,    16
  1000649496, 2018-12-05 11:28:52,    16
  1000649496, 2018-12-05 11:30:52,    16
  1000649496, 2018-12-05 11:32:52,    16
  1000649496, 2018-12-05 11:34:52,    16.1
  1000649496, 2018-12-05 11:36:52,    16.1
  1000649496, 2018-12-05 11:38:52,    16.1
  1000649496, 2018-12-05 11:40:52,    16.1
  1000649496, 2018-12-05 11:42:52,    16.1
  1000649496, 2018-12-05 11:44:52,    16.1
  1000649496, 2018-12-05 11:46:52,    16.1
  1000649496, 2018-12-05 11:48:52,    16
  1000649496, 2018-12-05 11:50:52,    16
  1000649496, 2018-12-05 11:52:52,    16
  1000649496, 2018-12-05 11:54:52,    16
  1000649496, 2018-12-05 11:56:52,    16
  1000649496, 2018-12-05 11:58:52,    16
  1000649496, 2018-12-05 12:00:52,    16.1
  1000649496, 2018-12-05 12:02:52,    16.1
  1000649496, 2018-12-05 12:04:52,    16.1
  1000649496, 2018-12-05 12:06:52,    16.1
  1000649496, 2018-12-05 12:08:52,    16
  1000649496, 2018-12-05 12:10:52,    16
  1000649496, 2018-12-05 12:12:52,    16
  1000649496, 2018-12-05 12:14:52,    16
  1000649496, 2018-12-05 12:16:52,    16
  1000649496, 2018-12-05 12:18:52,    16
  1000649496, 2018-12-05 12:20:52,    16
  1000649496, 2018-12-05 12:22:52,    16
  1000649496, 2018-12-05 12:24:52,    16
  1000649496, 2018-12-05 12:26:52,    16
  1000649496, 2018-12-05 12:28:52,    16
  1000649496, 2018-12-05 12:30:52,    16
  1000649496, 2018-12-08 08:08:52,    15.1
  1000649496, 2018-12-05 12:32:52,    16
  1000649496, 2018-12-05 12:34:52,    16
  1000649496, 2018-12-05 12:36:52,    16
  1000649496, 2018-12-05 12:38:52,    16

到目前为止,我的查询非常基础:

    SELECT SerialNumber, CombineDateTime, Temperature 
    FROM RawData
    WHERE Temperature > 16

我要记住的原则是,我选择数据集和order by date并遍历每一行,直到找到超过16的值。然后,我获取日期,然后遍历记录,直到找到<= 16的值,然后获取该日期和时间以及datediff()的{​​{1}}中的期间。

我知道您不应该遍历minutes记录,因此我正在考虑使用SQL,但是我不太确定该怎么做。

例如,我的预期结果是:

CTE

TIA

4 个答案:

答案 0 :(得分:1)

这看起来像是一个间隙和孤岛问题(连续> 16个温度和<= 16个温度需要组合在一起),一种解决方案如下:

DECLARE @threshold DECIMAL(18, 2) = 16;
WITH cte1 AS (
    SELECT *, CASE 
           -- first row itself is greater than threshold
           WHEN Temperature  >  @threshold  AND  LAG(Temperature)  OVER (PARTITION BY SerialNumber ORDER BY CombinDateTime) IS NULL      THEN 1
           -- next row is greater than threshold
           WHEN Temperature <=  @threshold  AND LEAD(Temperature)  OVER (PARTITION BY SerialNumber ORDER BY CombinDateTime) > @threshold THEN 1
           -- prev row is greater than threshold
           WHEN Temperature <=  @threshold  AND  LAG(Temperature)  OVER (PARTITION BY SerialNumber ORDER BY CombinDateTime) > @threshold THEN 1
    END AS chg
    FROM @t
), cte2 AS (
    SELECT *, SUM(chg) OVER (PARTITION BY SerialNumber ORDER BY CombinDateTime) AS grp
    FROM cte1
)
SELECT SerialNumber
     , MIN(CombinDateTime) AS StartDateTime
     , MAX(CombinDateTime) AS EndDateTime
     , DATEDIFF(SECOND, MIN(CombinDateTime), MAX(CombinDateTime)) / 60.0 AS Total
FROM cte2
GROUP BY SerialNumber, grp
HAVING MAX(Temperature) > @threshold

结果:

SerialNumber  StartDateTime        EndDateTime          Total
1000649496    2018-12-05 10:56:52  2018-12-05 11:24:52  28.000000
1000649496    2018-12-05 11:32:52  2018-12-05 11:46:52  14.000000
1000649496    2018-12-05 11:58:52  2018-12-05 12:06:52  8.000000

答案 1 :(得分:1)

具有LAG和滚动SUM窗口功能的解决方案:

DECLARE @ThresholdTemperature DECIMAL(3, 1) = 16

;WITH BreakMarker AS
(
    -- Determine if the temperature is above or below the threshold
    SELECT
        M.*,
        LimitMarker = CASE WHEN M.Temperature > @ThresholdTemperature THEN 0 ELSE 1 END
    FROM
        #Measures AS M
),
LaggedChange AS
(
    -- Determine at which point in time the temperature moves between the threshold
    SELECT
        B.*,
        TempChange = CASE WHEN B.LimitMarker = LAG(B.LimitMarker, 1, 0) OVER (
            PARTITION BY 
                B.SerialNumber 
            ORDER BY 
                B.CombinDateTime ASC) THEN 0 ELSE 1 END
    FROM
        BreakMarker AS B
),
BreakGroups AS
(
    -- Generate a group ID value to calculate MAX and MIN
    SELECT
        L.*,
        BreakGroup = SUM(TempChange) OVER (PARTITION BY L.SerialNumber ORDER BY L.CombinDateTime ASC)
    FROM
        LaggedChange AS L
)
SELECT
    B.SerialNumber,
    MinCombinDateTime = MIN(B.CombinDateTime),
    MaxCombinDateTime = MAX(B.CombinDateTime),
    MinutesOver = DATEDIFF(MINUTE, MIN(B.CombinDateTime), MAX(B.CombinDateTime))
FROM
    BreakGroups AS B
GROUP BY
    B.SerialNumber,
    B.BreakGroup
HAVING
    MIN(B.Temperature) > @ThresholdTemperature

结果:

SerialNumber    MinCombinDateTime           MaxCombinDateTime           MinutesOver
1000649496      2018-12-05 10:56:52.000     2018-12-05 11:24:52.000     28
1000649496      2018-12-05 11:34:52.000     2018-12-05 11:46:52.000     12
1000649496      2018-12-05 12:00:52.000     2018-12-05 12:06:52.000     6

您可以在此处检查CTE的临时结果,因此更容易理解逐步的逻辑:

SerialNumber    CombinDateTime              Temperature LimitMarker TempChange  BreakGroup
1000649496      2018-12-05 10:56:52.000     16.6        0           0           0
1000649496      2018-12-05 10:58:52.000     17.3        0           0           0
1000649496      2018-12-05 11:00:52.000     16.8        0           0           0
1000649496      2018-12-05 11:02:52.000     16.6        0           0           0
1000649496      2018-12-05 11:04:52.000     16.4        0           0           0
1000649496      2018-12-05 11:06:52.000     16.3        0           0           0
1000649496      2018-12-05 11:08:52.000     16.3        0           0           0
1000649496      2018-12-05 11:10:52.000     16.2        0           0           0
1000649496      2018-12-05 11:12:52.000     16.2        0           0           0
1000649496      2018-12-05 11:14:52.000     16.2        0           0           0
1000649496      2018-12-05 11:16:52.000     16.2        0           0           0
1000649496      2018-12-05 11:18:52.000     16.2        0           0           0
1000649496      2018-12-05 11:20:52.000     16.1        0           0           0
1000649496      2018-12-05 11:22:52.000     16.1        0           0           0
1000649496      2018-12-05 11:24:52.000     16.1        0           0           0
1000649496      2018-12-05 11:26:52.000     16.0        1           1           1
1000649496      2018-12-05 11:28:52.000     16.0        1           0           1
1000649496      2018-12-05 11:30:52.000     16.0        1           0           1
1000649496      2018-12-05 11:32:52.000     16.0        1           0           1
1000649496      2018-12-05 11:34:52.000     16.1        0           1           2
1000649496      2018-12-05 11:36:52.000     16.1        0           0           2
1000649496      2018-12-05 11:38:52.000     16.1        0           0           2
1000649496      2018-12-05 11:40:52.000     16.1        0           0           2
1000649496      2018-12-05 11:42:52.000     16.1        0           0           2
1000649496      2018-12-05 11:44:52.000     16.1        0           0           2
1000649496      2018-12-05 11:46:52.000     16.1        0           0           2
1000649496      2018-12-05 11:48:52.000     16.0        1           1           3
1000649496      2018-12-05 11:50:52.000     16.0        1           0           3
1000649496      2018-12-05 11:52:52.000     16.0        1           0           3
1000649496      2018-12-05 11:54:52.000     16.0        1           0           3
1000649496      2018-12-05 11:56:52.000     16.0        1           0           3
1000649496      2018-12-05 11:58:52.000     16.0        1           0           3
1000649496      2018-12-05 12:00:52.000     16.1        0           1           4
1000649496      2018-12-05 12:02:52.000     16.1        0           0           4
1000649496      2018-12-05 12:04:52.000     16.1        0           0           4
1000649496      2018-12-05 12:06:52.000     16.1        0           0           4
1000649496      2018-12-05 12:08:52.000     16.0        1           1           5
1000649496      2018-12-05 12:10:52.000     16.0        1           0           5
1000649496      2018-12-05 12:12:52.000     16.0        1           0           5
1000649496      2018-12-05 12:14:52.000     16.0        1           0           5
1000649496      2018-12-05 12:16:52.000     16.0        1           0           5
1000649496      2018-12-05 12:18:52.000     16.0        1           0           5
1000649496      2018-12-05 12:20:52.000     16.0        1           0           5
1000649496      2018-12-05 12:22:52.000     16.0        1           0           5
1000649496      2018-12-05 12:24:52.000     16.0        1           0           5
1000649496      2018-12-05 12:26:52.000     16.0        1           0           5
1000649496      2018-12-05 12:28:52.000     16.0        1           0           5
1000649496      2018-12-05 12:30:52.000     16.0        1           0           5
1000649496      2018-12-05 12:32:52.000     16.0        1           0           5
1000649496      2018-12-05 12:34:52.000     16.0        1           0           5
1000649496      2018-12-05 12:36:52.000     16.0        1           0           5
1000649496      2018-12-05 12:38:52.000     16.0        1           0           5
1000649496      2018-12-08 08:08:52.000     15.1        1           0           5

答案 2 :(得分:-1)

您要求和日期部分的总和,然后按序列号分组

SELECT SUM(DATEPART(minute, [CombinDateTime])) AS total_call_time , [SerialNumber] FROM [dbo].[Table_1] WHERE [Temperature]>16 GROUP BY [SerialNumber];

答案 3 :(得分:-1)

您需要为每行分配一个组。可以将此组分配为超过每行或每行之后的每一行的值的数量。这将在组中包括“关闭”行。

因此,这些组被分配为:

SELECT rd.*,
       SUM(CASE WHEN Temperature <= 16 THEN 1 ELSE 0 END) OVER (PARTITION BY SerialNumber ORDER BY CombineDateTime DESC) as grp
FROM RawData rd;

然后,您可以使用聚合和过滤。因此,这将返回您想要的时间跨度:

SELECT SerialNumber,
       MIN(CombineDateTime), MAX(CombineDateTime)
FROM (SELECT rd.*,
             SUM(CASE WHEN Temperature <= 16 THEN 1 ELSE 0 END) OVER (PARTITION BY SerialNumber ORDER BY CombineDateTime DESC) as grp
      FROM RawData rd
     ) rd
WHERE Temperature > 16
GROUP BY SerialNumber, grp;

最后,您可以计算总分钟数:

SELECT SUM(DATEDIFF(minute, min_cdt, max_cdt)
FROM (SELECT SerialNumber,
             MIN(CombineDateTime) as min_cdt,
             MAX(CombineDateTime) as max_cdt
      FROM (SELECT rd.*,
                   SUM(CASE WHEN Temperature <= 16 THEN 1 ELSE 0 END) OVER (PARTITION BY SerialNumber ORDER BY CombineDateTime DESC) as grp
            FROM RawData rd
           ) rd
      WHERE Temperature > 16
      GROUP BY SerialNumber, grp
     ) s;