SQL Oracle计数集群

时间:2015-07-08 04:22:24

标签: sql oracle

我有一个基于时间戳的数据集。

     Date                 Value
07-Jul-15 12:05:00          1  
07-Jul-15 12:10:00          1 
07-Jul-15 12:15:00          1 
07-Jul-15 12:20:00          0 
07-Jul-15 12:25:00          0 
07-Jul-15 12:30:00          0 
07-Jul-15 12:35:00          1 
07-Jul-15 12:40:00          1 
07-Jul-15 12:45:00          1 
07-Jul-15 12:50:00          1 
07-Jul-15 12:55:00          0 
07-Jul-15 13:00:00          0 
07-Jul-15 13:05:00          1 
07-Jul-15 13:10:00          1 
07-Jul-15 13:15:00          1 
07-Jul-15 13:20:00          0 
07-Jul-15 13:25:00          0 

我想查询并返回

  
      
  1. 停机次数:此情况下的停机次数为3,基于0为ON,1为OFF。
  2.   
  3. 每次关闭之间的时间段

         

    示例:

         
        
    1. From:07-Jul-15 12:05:00 To:07-Jul-15 12:15:00持续时间:15分钟
    2.   
    3. 来自:07-Jul-15 12:35:00致:07-Jul-15 12:50:00持续时间:20分钟
    4.   
  4.   

我正在使用Oracle

4 个答案:

答案 0 :(得分:1)

您可以在sqlfiddle上测试我的答案:http://www.sqlfiddle.com/#!4/9c6a69/16

  
    

测试数据

  
create table test (dttm date, onoff number);

insert into test values (to_date('07-Jul-15 12:05:00', 'DD-MM-YY HH24:MI:SS'), 1 );
insert into test values (to_date('07-Jul-15 12:10:00', 'DD-MM-YY HH24:MI:SS'), 1 );
insert into test values (to_date('07-Jul-15 12:15:00', 'DD-MM-YY HH24:MI:SS'), 1 );
insert into test values (to_date('07-Jul-15 12:20:00', 'DD-MM-YY HH24:MI:SS'), 0 );
insert into test values (to_date('07-Jul-15 12:25:00', 'DD-MM-YY HH24:MI:SS'), 0 );
insert into test values (to_date('07-Jul-15 12:30:00', 'DD-MM-YY HH24:MI:SS'), 0 );
insert into test values (to_date('07-Jul-15 12:35:00', 'DD-MM-YY HH24:MI:SS'), 1 );
insert into test values (to_date('07-Jul-15 12:40:00', 'DD-MM-YY HH24:MI:SS'), 1 );
insert into test values (to_date('07-Jul-15 12:45:00', 'DD-MM-YY HH24:MI:SS'), 1 );
insert into test values (to_date('07-Jul-15 12:50:00', 'DD-MM-YY HH24:MI:SS'), 1 );
insert into test values (to_date('07-Jul-15 12:55:00', 'DD-MM-YY HH24:MI:SS'), 0 );
insert into test values (to_date('07-Jul-15 13:00:00', 'DD-MM-YY HH24:MI:SS'), 0 );
insert into test values (to_date('07-Jul-15 13:05:00', 'DD-MM-YY HH24:MI:SS'), 1 );
insert into test values (to_date('07-Jul-15 13:10:00', 'DD-MM-YY HH24:MI:SS'), 1 );
insert into test values (to_date('07-Jul-15 13:15:00', 'DD-MM-YY HH24:MI:SS'), 1 );
insert into test values (to_date('07-Jul-15 13:20:00', 'DD-MM-YY HH24:MI:SS'), 0 );
insert into test values (to_date('07-Jul-15 13:25:00', 'DD-MM-YY HH24:MI:SS'), 0 );

首先,删除所有不必要的列并仅保留开/关列:

select t.dttm, t.onoff from test t
where not exists (select 'X' from test tt 
                  where tt.dttm =
                    (select max(ttt.dttm) from test ttt where ttt.dttm < t.dttm)
             and tt.onoff = t.onoff)
  
    

停机次数:

  
with data as (
select t.dttm, t.onoff from test t
where not exists (select 'X' from test tt 
                 where tt.dttm =
                    (select max(ttt.dttm) from test ttt where ttt.dttm < t.dttm)
                 and tt.onoff = t.onoff)
)
select count(*) from data d where d.onoff=0;                                
  
    

准时:

  
with data as (
select t.dttm, t.onoff from test t
where not exists (select 'X' from test tt 
                 where tt.dttm =
                    (select max(ttt.dttm) from test ttt where ttt.dttm < t.dttm)
                 and tt.onoff = t.onoff)
)
select d1.dttm as ontime, 
d0.dttm as offtime, 
(d0.dttm - d1.dttm) * 24 * 60 as duration 
from data d0, data d1 
where d1.onoff=1 
and d0.dttm = (select min(dd0.dttm) from data dd0 where dd0.dttm > d1.dttm);                                

答案 1 :(得分:1)

在ORACLE中使用LEAD和LAG函数可以构建这些查询:

1.关闭次数:

WITH IntTable AS
( SELECT * FROM
  (
   SELECT dt b_date,value,LEAD(dt) OVER (ORDER BY dt) e_date  FROM
     (
        select "Date" dt,"Value" value,
               LAG("Value") OVER (ORDER BY "Date") pvalue,
               LEAD("Value") OVER (ORDER BY "Date") nvalue
        from T
     ) T1
     WHERE pvalue is NULL or value<>pvalue or nvalue is NULL 
   )
WHERE E_DATE is NOT NULL
)
SELECT COUNT(*) FROM IntTable where value = 0 

SQLFiddle demo

2.每次关闭之间的时间

WITH IntTable AS
( SELECT * FROM
  (
   SELECT dt b_date,value,LEAD(dt) OVER (ORDER BY dt) e_date  FROM
     (
        select "Date" dt,"Value" value,
               LAG("Value") OVER (ORDER BY "Date") pvalue,
               LEAD("Value") OVER (ORDER BY "Date") nvalue
        from T
     ) T1
     WHERE pvalue is NULL or value<>pvalue or nvalue is NULL 
   )
WHERE E_DATE is NOT NULL
)
SELECT b_date,e_date, (e_date-b_date) * 60 * 24 FROM IntTable where value = 1 

SQLFiddle demo

答案 2 :(得分:0)

您的问题有两个部分,两个部分都需要在两个不同的查询中处理。由于输出基于两组不同的行。

<强>设置

SQL> CREATE TABLE t AS SELECT * FROM(WITH DATA(dt, status) AS(
  2  SELECT to_date('07-Jul-15 12:05:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 1 FROM dual UNION ALL
  3  SELECT to_date('07-Jul-15 12:10:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 1  FROM dual UNION ALL
  4  SELECT to_date('07-Jul-15 12:15:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 1  FROM dual UNION ALL
  5  SELECT to_date('07-Jul-15 12:20:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 0  FROM dual UNION ALL
  6  SELECT to_date('07-Jul-15 12:25:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 0  FROM dual UNION ALL
  7  SELECT to_date('07-Jul-15 12:30:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 0  FROM dual UNION ALL
  8  SELECT to_date('07-Jul-15 12:35:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 1  FROM dual UNION ALL
  9  SELECT to_date('07-Jul-15 12:40:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 1  FROM dual UNION ALL
 10  SELECT to_date('07-Jul-15 12:45:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 1  FROM dual UNION ALL
 11  SELECT to_date('07-Jul-15 12:50:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 1  FROM dual UNION ALL
 12  SELECT to_date('07-Jul-15 12:55:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 0  FROM dual UNION ALL
 13  SELECT to_date('07-Jul-15 13:00:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 0  FROM dual UNION ALL
 14  SELECT to_date('07-Jul-15 13:05:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 1  FROM dual UNION ALL
 15  SELECT to_date('07-Jul-15 13:10:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 1  FROM dual UNION ALL
 16  SELECT to_date('07-Jul-15 13:15:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 1  FROM dual UNION ALL
 17  SELECT to_date('07-Jul-15 13:20:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 0  FROM dual UNION ALL
 18  SELECT to_date('07-Jul-15 13:25:00', 'dd-Mon-rr hh24:mi:ss', 'NLS_DATE_LANGUAGE=AMERICAN'), 0  FROM dual
 19  ) SELECT * FROM DATA);

Table created.

表格数据

SQL> SELECT * FROM t;

DT                     STATUS
------------------ ----------
07-Jul-15 12:05:00          1
07-Jul-15 12:10:00          1
07-Jul-15 12:15:00          1
07-Jul-15 12:20:00          0
07-Jul-15 12:25:00          0
07-Jul-15 12:30:00          0
07-Jul-15 12:35:00          1
07-Jul-15 12:40:00          1
07-Jul-15 12:45:00          1
07-Jul-15 12:50:00          1
07-Jul-15 12:55:00          0
07-Jul-15 13:00:00          0
07-Jul-15 13:05:00          1
07-Jul-15 13:10:00          1
07-Jul-15 13:15:00          1
07-Jul-15 13:20:00          0
07-Jul-15 13:25:00          0

17 rows selected.
  
      
  1. 停机次数:此情况下的停机次数为3,基于0为ON,1为OFF。
  2.   

您需要使用 LAG()分析功能。

SQL> SELECT TO_CHAR(dt, 'dd-Mon-rr hh24:mi:ss') dt,
  2    status
  3  FROM
  4    (SELECT t.*,
  5      CASE
  6        WHEN lag(status) OVER(ORDER BY dt) <> status
  7        THEN 1
  8        ELSE 0
  9      END chg
 10    FROM t
 11    )
 12  WHERE status = 0
 13  AND chg      =1;

DT                     STATUS
------------------ ----------
07-Jul-15 12:20:00          0
07-Jul-15 12:55:00          0
07-Jul-15 13:20:00          0

因此,输出中有3行,这意味着发生了3次关闭事件。要获得计数,您只需使用 COUNT 功能。

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

    示例:

         
        
    1. From:07-Jul-15 12:05:00 To:07-Jul-15 12:15:00持续时间:15分钟
    2.   
    3. 来自:07-Jul-15 12:35:00致:07-Jul-15 12:50:00持续时间:20分钟
    4.   

再一次,您需要使用 LAG()分析功能。日期之间的差异返回天数。要将其转换为分钟数,请将其乘以 24 * 60

SQL> SELECT * FROM(
  2  SELECT t.*,
  3      CASE
  4        WHEN lag(status) OVER(ORDER BY dt) <> status
  5        THEN 1
  6        ELSE 0
  7      END chg,
  8      24*60*(dt - lag(dt) over(order by dt)) gap
  9    FROM t
 10    ) t
 11  WHERE status =1 and chg =0;

DT                     STATUS        CHG        GAP
------------------ ---------- ---------- ----------
07-Jul-15 12:05:00          1          0
07-Jul-15 12:10:00          1          0          5
07-Jul-15 12:15:00          1          0          5
07-Jul-15 12:40:00          1          0          5
07-Jul-15 12:45:00          1          0          5
07-Jul-15 12:50:00          1          0          5
07-Jul-15 13:10:00          1          0          5
07-Jul-15 13:15:00          1          0          5

8 rows selected.

SQL>

因此,根据上述查询,要查找系统启动时的总时间,请使用 SUM

SQL> SELECT SUM(gap) on_minutes FROM(
  2  SELECT t.*,
  3      CASE
  4        WHEN lag(status) OVER(ORDER BY dt) <> status
  5        THEN 1
  6        ELSE 0
  7      END chg,
  8      24*60*(dt - lag(dt) over(order by dt)) gap
  9    FROM t
 10    ) t
 11  WHERE status =1 and chg =0;

ON_MINUTES
----------
        35

SQL>

因此,该系统适用于35 minutes

答案 3 :(得分:0)

您好我已尝试使用以下代码,它会按预期显示结果

#lang racket
(require math)
(require plot/no-gui)

(plot-file (list (axes)
            (inverse-interval (λ (x) 1)
                              (λ (x) -1)
                              -3.00000 3.000000)
            (function (lambda (x) (* (expt 3 x) (sin (* 20 x)))) -1 1))
      "images/plot_000000.jpg"
      #:y-min -4
      #:y-max 4)