我有下表:
SystemDown SystemUp
------------------------------------------------
NULL 2018-07-05 15:02:11.903
NULL 2018-07-05 15:02:17.903
NULL 2018-07-05 15:02:23.903
NULL 2018-07-05 15:02:29.907
NULL 2018-07-05 15:02:35.907
NULL 2018-07-05 15:02:41.903
NULL 2018-07-05 15:02:05.903
2018-07-05 15:02:41.903 NULL
2018-07-05 15:04:05.907 NULL
NULL 2018-07-05 15:06:40.433
NULL 2018-07-05 15:07:10.430
NULL 2018-07-05 15:07:40.430
NULL 2018-07-05 15:08:10.430
我要创建此表:
Status StartDate EndDate
-------------------------------------------------------------
UP 2018-07-05 15:02:05.903 2018-07-05 15:02:41.903
Down 2018-07-05 15:02:41.903 2018-07-05 15:04:05.907
UP 2018-07-05 15:06:40.433 2018-07-05 15:08:10.430
其中间隔由每个间隔中的第一个和最后一个时间戳定义。
有什么建议吗?
答案 0 :(得分:2)
以下似乎有效:
;WITH CountCTE AS (
SELECT SystemDown, SystemUp,
ROW_NUMBER() OVER (ORDER BY COALESCE(SystemDown, SystemUp)) AS rn,
COUNT(SystemUp) OVER (ORDER BY SystemUp) AS countUp,
COUNT(SystemDown) OVER (ORDER BY SystemDown) AS countDown
FROM mytable
), GroupCTE AS (
SELECT SystemDown, SystemUp,
COALESCE(SystemDown, SystemUp) AS t,
IIF(SystemUp IS NOT NULL, 'UP', 'DOWN') AS Status,
rn - countUp AS grpUp,
rn - countDown AS grpDown
FROM CountCTE
)
SELECT Status,
MIN(t) AS StartDate,
MAX(t) AS EndDate
FROM GroupCTE
GROUP BY Status,
IIF(Status = 'UP', grpUp, grpDown)
ORDER BY StartDate
如果您检查GroupCTE
的中间结果,则可以深入了解其工作原理:
SystemDown SystemUp Status grpUp grpDown
------------------------------------------------------------------------
NULL 2018-07-05 15:02:05.903 UP 0 1
NULL 2018-07-05 15:02:11.903 UP 0 2
NULL 2018-07-05 15:02:17.903 UP 0 3
NULL 2018-07-05 15:02:23.903 UP 0 4
NULL 2018-07-05 15:02:29.907 UP 0 5
NULL 2018-07-05 15:02:35.907 UP 0 6
NULL 2018-07-05 15:02:41.903 UP 0 7
NULL 2018-07-05 15:06:40.433 UP 2 10
NULL 2018-07-05 15:07:10.430 UP 2 11
NULL 2018-07-05 15:07:40.430 UP 2 12
NULL 2018-07-05 15:08:10.430 UP 2 13
2018-07-05 15:02:41.903 NULL DOWN 8 7
2018-07-05 15:04:05.907 NULL DOWN 9 7
答案 1 :(得分:1)
您可以使用ROW_NUMBER()
来生成排名,然后将它们放在一起以将间隔进行分组(其余一致的记录是连续的,从而获得相同的组号)。
IF OBJECT_ID('tempdb..#YourTable') IS NOT NULL
DROP TABLE #YourTable
CREATE TABLE #YourTable (
SystemDown DATETIME,
SystemUp DATETIME)
INSERT INTO #YourTable (
SystemDown,
SystemUp)
VALUES
(NULL, '2018-07-05 15:02:05.903'),
(NULL, '2018-07-05 15:02:11.903'),
(NULL, '2018-07-05 15:02:17.903'),
(NULL, '2018-07-05 15:02:23.903'),
(NULL, '2018-07-05 15:02:29.907'),
(NULL, '2018-07-05 15:02:35.907'),
(NULL, '2018-07-05 15:02:41.903'),
('2018-07-05 15:02:41.903', NULL),
('2018-07-05 15:04:05.907', NULL),
(NULL, '2018-07-05 15:06:40.433'),
(NULL, '2018-07-05 15:07:10.430'),
(NULL, '2018-07-05 15:07:40.430'),
(NULL, '2018-07-05 15:08:10.430')
;WITH Rankings AS
(
SELECT
SystemDown = T.SystemDown,
SystemUp = T.SystemUp,
GeneralRanking = ROW_NUMBER() OVER (ORDER BY ISNULL(T.SystemDown, T.SystemUp) ASC),
UpRanking = ROW_NUMBER() OVER (ORDER BY T.SystemUp ASC),
DownRanking = ROW_NUMBER() OVER (ORDER BY T.SystemDown ASC)
FROM
#YourTable AS T
),
UpTimes AS
(
SELECT
Status = 'Up',
StartDate = MIN(R.SystemUp),
EndDate = MAX(R.SystemUp)
FROM
Rankings AS R
WHERE
R.SystemUp IS NOT NULL
GROUP BY
R.GeneralRanking - R.UpRanking
),
DownTimes AS
(
SELECT
Status = 'Down',
StartDate = MIN(R.SystemDown),
EndDate = MAX(R.SystemDown)
FROM
Rankings AS R
WHERE
R.SystemDown IS NOT NULL
GROUP BY
R.GeneralRanking - R.DownRanking
)
SELECT
U.Status,
U.StartDate,
U.EndDate
FROM
UpTimes AS U
UNION ALL
SELECT
D.Status,
D.StartDate,
D.EndDate
FROM
DownTimes AS D
ORDER BY
StartDate ASC
结果:
Status StartDate EndDate
Up 2018-07-05 15:02:05.903 2018-07-05 15:02:41.903
Down 2018-07-05 15:02:41.903 2018-07-05 15:04:05.907
Up 2018-07-05 15:06:40.433 2018-07-05 15:08:10.430