表格格式如下。
Id name value logdatetime
*************************************************
1 a 65 2017-03-08 00:13:00.000
2 a 63 2017-03-08 00:14:00.000
3 a 72 2017-03-08 00:15:00.000
4 a 120 2017-03-08 00:16:00.000
5 a 45 2017-03-08 00:17:00.000
6 a 32 2017-03-08 00:18:00.000
7 a 53 2017-03-08 00:19:00.000
8 a 59 2017-03-08 00:20:00.000
9 a 21 2017-03-08 00:21:00.000
从上表我需要使用sql查询生成下表,它基本上必须检查大于50的值并显示如下数据
name startdate enddate
********************************************************************
a 2017-03-08 00:13:00.000 2017-03-08 00:16:00.000
a 2017-03-08 00:19:00.000 2017-03-08 00:21:00.000
请帮我解决这个问题。
最佳答案
尝试使用以下内容
CREATE TABLE #TestData(
Id int,
name varchar(10),
value int,
logdatetime datetime
)
INSERT #TestData(Id,name,value,logdatetime)VALUES
(1,'a',65,'2017-03-08 00:13:00.000'),
(2,'a',63,'2017-03-08 00:14:00.000'),
(3,'a',72,'2017-03-08 00:15:00.000'),
(4,'a',120,'2017-03-08 00:16:00.000'),
(5,'a',45,'2017-03-08 00:17:00.000'), -- separator 1
(6,'a',32,'2017-03-08 00:18:00.000'), -- separator 2
(7,'a',53,'2017-03-08 00:19:00.000'),
(8,'a',59,'2017-03-08 00:20:00.000'),
(9,'a',21,'2017-03-08 00:21:00.000') -- separator 3
SELECT
name,
MIN(logdatetime) [start time],
MAX(logdatetime) [end time]
FROM
(
SELECT
*,
SUM(IsSeparator)OVER(
PARTITION BY name
ORDER BY logdatetime,Id
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) SeparatorCount
FROM
(
SELECT
*,
--IIF(value<=50,1,0) IsSeparator -- it's a special marker
CASE WHEN value<=50 THEN 1 ELSE 0 END IsSeparator -- you can use CASE instead IIF
FROM #TestData
) q
) q
WHERE value>50 -- exclude values less 50
GROUP BY name,SeparatorCount -- use SeparatorCount here
DROP TABLE #TestData
我在 SQLServer 2014
上测试过它。
SQL fiddle -http://sqlfiddle.com/#!6/ff80e/1
或者你可以使用递归 CTE 的另一个变体
;WITH numCTE AS(
SELECT *,ROW_NUMBER()OVER(PARTITION BY name ORDER BY logdatetime,Id) n
FROM #TestData
),
groupCTE AS(
SELECT name,logdatetime,value,n,1 groupNum
FROM numCTE
WHERE n=1
UNION ALL
SELECT n.name,n.logdatetime,n.value,n.n,
--g.groupNum+IIF(n.value<=50,1,0)
g.groupNum+CASE WHEN n.value<=50 THEN 1 ELSE 0 END
FROM numCTE n
JOIN groupCTE g ON n.name=g.name AND n.n=g.n+1
)
SELECT
name,
MIN(logdatetime) [start time],
MAX(logdatetime) [end time]
FROM groupCTE
WHERE value>50
GROUP BY name,groupNum
但我认为第一个变体更好。
还有一个变体。它比第一个变体短。
SELECT
name,
MIN(logdatetime) [start time],
MAX(logdatetime) [end time]
FROM
(
SELECT
*,
SUM(CASE WHEN value<=50 THEN 1 ELSE 0 END)OVER(
PARTITION BY name
ORDER BY logdatetime,Id
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) groupNum
FROM #TestData
) q
WHERE value>50
GROUP BY name,groupNum
关于sql - 同一列中的日期差异,基于表的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47827475/