我希望能够以分钟为单位计算温度列超过特定温度的总时间。例如,我想知道温度在16分钟以上达到了多长时间。
如果12:28
的读数为16
,而12:30
的读数为17
,那么我们说的是从12:28
到12:30
,则值为17
。
此外,如果第一个或唯一读数高于x(17),则将是两分钟,因为启动设备时,需要x分钟(在这种情况下为2分钟)才能进行第一次读数。
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
答案 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;