假设我有一张包含各种事件及其开始时间的表格:
EventTime EventCode EventDescription
--------- --------- ----------------
2014-01-23 00:03:32 430 Running
2014-01-23 00:04:35 430 Running
2014-01-23 00:06:37 430 Running
2014-01-23 00:11:45 430 Running
2014-01-23 00:32:46 721 Stopped
2014-01-23 00:34:49 721 Stopped
2014-01-23 00:41:52 430 Running
2014-01-23 01:03:54 721 Stopped
2014-01-23 01:04:55 430 Running
根据这些数据,我想得到所有间隔的开始时间和持续时间。含义,eventCode 721的记录的startTime和eventCode 430的第一个连续事件的startTime,反之亦然,如下所示:
START END STATUS
----------- ---------- ----------------
2014-01-23 00:03:32 2014-01-23 00:32:46 Running
2014-01-23 00:32:46 2014-01-23 00:41:52 Stopped
2014-01-23 00:41:52 2014-01-23 01:03:54 Running
2014-01-23 01:03:54 2014-01-23 01:04:55 Stopped
我已经看到了OVER语法的用法,但在我看到的例子中,它被用于数据集中的连续行。表a可以具有许多相同的状态。
如示例中那样转换数据的最佳(也是最高效)方法是什么?谢谢!
答案 0 :(得分:3)
一种方法
WITH cte AS
(
SELECT eventcode, eventdescription, MIN(eventtime) starttime, MAX(eventtime) endtime,
ROW_NUMBER() OVER (ORDER BY MIN(eventtime)) rnum
FROM
(
SELECT t.*,
ROW_NUMBER() OVER (ORDER BY eventtime) rnum,
ROW_NUMBER() OVER (PARTITION BY eventcode ORDER BY eventtime) grnum
FROM table1 t
) q
GROUP BY eventcode, eventdescription, rnum - grnum
)
SELECT t1.starttime, t2.starttime endtime, t1.eventdescription status
FROM cte t1 JOIN cte t2
ON t1.rnum = t2.rnum - 1
ORDER BY starttime, endtime
输出:
| STARTTIME | ENDTIME | STATUS | |--------------------------------|--------------------------------|---------| | January, 23 2014 00:03:32+0000 | January, 23 2014 00:32:46+0000 | Running | | January, 23 2014 00:32:46+0000 | January, 23 2014 00:41:52+0000 | Stopped | | January, 23 2014 00:41:52+0000 | January, 23 2014 01:03:54+0000 | Running | | January, 23 2014 01:03:54+0000 | January, 23 2014 01:04:55+0000 | Stopped |
这是 SQLFiddle 演示
答案 1 :(得分:2)
这类似于peterm的答案,只少了一个ROW_NUMBER ......
您可以将LEFT联接更改为INNER:
WITH cte (EventTime, EventCode, EventDescription, rn, rn2) AS
(
SELECT
EventTime, EventCode, EventDescription,
ROW_NUMBER() OVER (ORDER BY EventTime) AS rn,
ROW_NUMBER() OVER (PARTITION BY EventCode ORDER BY EventTime) AS rn2
FROM Table1
)
SELECT MIN(t1.EventTime), MAX(t2.EventTime), t1.EventDescription
FROM cte AS t1 LEFT JOIN cte AS t2
ON t2.rn = t1.rn+1
GROUP BY t2.rn-t1.rn2, t1.EventDescription
ORDER BY 1