sql - 计算值大于 x 的时间(以分钟为单位)

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

我希望能够计算温度列超过特定温度的总时间(以分钟为单位)。例如,我想知道温度超过 16 度的分钟数。

如果读数在 12:2816并阅读 12:3017 ,我们是说来自 12:2812:30 , 值为 17 .

此外,如果第一个或唯一一个读数高于 x (17),则这将是两分钟,因为设备启动后需要 x 分钟(在本例中为 2 分钟)才能获取第一个读数。

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

  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() minutes 期间.

我知道你不应该遍历 SQL记录,所以我正在考虑使用 CTE ,但我不太确定该怎么做。

例如,我的预期结果是:

    SerialNumber, MinutesOver 
    1000649496, 1186

TIA

最佳答案

这看起来像是一个间隙和孤岛问题(连续 > 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

关于sql - 计算值大于 x 的时间(以分钟为单位),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54476888/

相关文章:

SQL查询获取表中的单词数

sql - MERGE 语句执行时间太长(仅针对 1 条记录)。 (MS-SQL Server 2012)

python - 在 for 循环中附加数据框

javascript - 如何通过 JavaScript 从主要世界时钟网站获取时区或日期?

sql - FALSE 和 TRUE 与 NULL 和 TRUE

sql - 初级 SQL 部分 : avoiding repeated expression

sql-server - SQL Server - 获取具有 MDF 和 LDF 文件位置的所有数据库

ruby - DataMapper 日期时间条件

mysql - 查找并删除 SQL 记录(如果它们发生在 8 小时内)(最近的记录除外)

sql-server - SQL 中的二元运算符 OR?