按时间间隔进行SQL分组

时间:2015-07-08 09:32:56

标签: sql oracle

我有一个基于时间戳的数据集。数据集在5分钟的时间间隔内记录每次关闭事件。如果在特定的5分钟内发生关闭,则添加记录,否则不记录。因此,没有记录意味着系统已经恢复

     Date          
07-Jul-15 12:05:00 
07-Jul-15 12:10:00
07-Jul-15 12:15:00
07-Jul-15 12:35:00
07-Jul-15 12:40:00
07-Jul-15 12:45:00
07-Jul-15 12:50:00
07-Jul-15 13:05:00
07-Jul-15 13:10:00
07-Jul-15 13:15:00 

我想查询并返回

  

1.关闭次数:在这种情况下,关闭次数为3,基于

12:15 to 12:35 
12:50 to 13:05

系统已恢复

  
      
  1. 每次关闭之间的时间段
  2.         

    示例:

         

    1.From:07-Jul-15 12:05:00 To:07-Jul-15 12:15:00持续时间:15分钟

         

    2.From:07-Jul-15 12:35:00 To:07-Jul-15 12:50:00持续时间:20分钟

similar个问题,但这个问题需要一个非常不同的解决方案。

会欣赏一个小提琴的例子

2 个答案:

答案 0 :(得分:1)

WITH changes AS (
  SELECT "DATE",
         CASE WHEN LAG( "DATE" ) OVER ( ORDER BY "DATE" ) + INTERVAL '5' MINUTE = "DATE" THEN 0 ELSE 1 END AS has_changed_group
  FROM   TEST
), grps AS (
  SELECT "DATE",
         SUM( has_changed_group ) OVER ( ORDER BY "DATE" ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS grp
  FROM   changes
)
SELECT MIN( "DATE" ) AS shutdown_start,
       MAX( "DATE" ) AS shutdown_end,
       MAX( "DATE" ) - MIN( "DATE" ) + INTERVAL '5' MINUTE AS shutdown_duration
FROM   grps
GROUP BY grp;

<强>输出:

SHUTDOWN_START               SHUTDOWN_END                 SHUTDOWN_DURATION
---------------------------- ---------------------------- -----------------
07-JUL-15 12.05.00.000000000 07-JUL-15 12.15.00.000000000 0 0:15:0.0        
07-JUL-15 12.35.00.000000000 07-JUL-15 12.50.00.000000000 0 0:20:0.0        
07-JUL-15 13.05.00.000000000 07-JUL-15 13.15.00.000000000 0 0:15:0.0  

编辑 - 多台计算机:

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE TEST ( MACHINE_ID, "DATE" ) AS
          SELECT 1, TIMESTAMP '2015-07-07 12:05:00' FROM DUAL
UNION ALL SELECT 1, TIMESTAMP '2015-07-07 12:10:00' FROM DUAL
UNION ALL SELECT 1, TIMESTAMP '2015-07-07 12:15:00' FROM DUAL
UNION ALL SELECT 1, TIMESTAMP '2015-07-07 12:35:00' FROM DUAL
UNION ALL SELECT 1, TIMESTAMP '2015-07-07 12:40:00' FROM DUAL
UNION ALL SELECT 1, TIMESTAMP '2015-07-07 12:45:00' FROM DUAL
UNION ALL SELECT 1, TIMESTAMP '2015-07-07 12:50:00' FROM DUAL
UNION ALL SELECT 1, TIMESTAMP '2015-07-07 13:05:00' FROM DUAL
UNION ALL SELECT 1, TIMESTAMP '2015-07-07 13:10:00' FROM DUAL
UNION ALL SELECT 1, TIMESTAMP '2015-07-07 13:15:00' FROM DUAL
UNION ALL SELECT 2, TIMESTAMP '2015-07-07 12:35:00' FROM DUAL
UNION ALL SELECT 2, TIMESTAMP '2015-07-07 12:40:00' FROM DUAL
UNION ALL SELECT 2, TIMESTAMP '2015-07-07 12:45:00' FROM DUAL
UNION ALL SELECT 2, TIMESTAMP '2015-07-07 13:00:00' FROM DUAL
UNION ALL SELECT 2, TIMESTAMP '2015-07-07 13:05:00' FROM DUAL
UNION ALL SELECT 2, TIMESTAMP '2015-07-07 13:10:00' FROM DUAL
UNION ALL SELECT 2, TIMESTAMP '2015-07-07 13:15:00' FROM DUAL;

查询1

WITH changes AS (
  SELECT MACHINE_ID,
         "DATE",
         CASE WHEN LAG( "DATE" ) OVER ( PARTITION BY MACHINE_ID ORDER BY "DATE" ) + INTERVAL '5' MINUTE = "DATE" THEN 0 ELSE 1 END AS has_changed_group
  FROM   TEST
), grps AS (
  SELECT MACHINE_ID,
         "DATE",
         SUM( has_changed_group ) OVER ( PARTITION BY MACHINE_ID ORDER BY "DATE" ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS grp
  FROM   changes
)
SELECT MACHINE_ID,
       TO_CHAR( MIN( "DATE" ), 'YYYY-MM-DD HH24:MI:SS' ) AS shutdown_start,
       TO_CHAR( MAX( "DATE" ), 'YYYY-MM-DD HH24:MI:SS' ) AS shutdown_end,
       TO_CHAR( MAX( "DATE" ) - MIN( "DATE" ) + INTERVAL '5' MINUTE ) AS shutdown_duration
FROM   grps
GROUP BY MACHINE_ID, grp
ORDER BY 1,2

<强> Results

| MACHINE_ID |      SHUTDOWN_START |        SHUTDOWN_END |             SHUTDOWN_DURATION |
|------------|---------------------|---------------------|-------------------------------|
|          1 | 2015-07-07 12:05:00 | 2015-07-07 12:15:00 | +000000000 00:15:00.000000000 |
|          1 | 2015-07-07 12:35:00 | 2015-07-07 12:50:00 | +000000000 00:20:00.000000000 |
|          1 | 2015-07-07 13:05:00 | 2015-07-07 13:15:00 | +000000000 00:15:00.000000000 |
|          2 | 2015-07-07 12:35:00 | 2015-07-07 12:45:00 | +000000000 00:15:00.000000000 |
|          2 | 2015-07-07 13:00:00 | 2015-07-07 13:15:00 | +000000000 00:20:00.000000000 |

答案 1 :(得分:0)

解决方案使用Tom Kyte&#34;&#34;结束&#34;技术:

with test1 as (
select mydate,
-- mark starting records in each group
case when NVL((mydate - lag(mydate) over (order by mydate))*24*60,10) > 5 
then row_number() over (order by mydate) end as group_id
from test),
test2 as (
select mydate,
-- propagate group_id to all records
LAST_VALUE(group_id IGNORE NULLS) over (order by mydate) as group_id
from test1) 
select  min(mydate) shutdown_from, max(mydate) shutdown_to
from test2
group by group_id;

<强>输出

SHUTDOWN_FROM       SHUTDOWN_TO       
------------------- -------------------
07.07.0015 12:05:00 07.07.0015 12:15:00 
07.07.0015 12:35:00 07.07.0015 12:50:00 
07.07.0015 13:05:00 07.07.0015 13:15:00