我的表MEASUREMENTS(Oracle SQL 12)有3列:DT-测量时间戳,MEASUREMENT-值,THRESHOLD-上限。
有时测量值超出阈值。尝试计算测量值高于阈值的时间段。
DT | MEASUREMENT | THRESHOLD ---------------+-------------+-------------------- 04.08.16 01:10 | 60,5 | 70,0 04.08.16 01:20 | 65,5 | 70,0 04.08.16 01:30 | 68,1 | 70,0 04.08.16 01:40 | 70,1* | 70,0 //period start 04.08.16 01:50 | 70,1* | 70,0 04.08.16 02:00 | 70,75* | 70,0 //period end 04.08.16 02:10 | 53,5 | 70,0 04.08.16 02:20 | 50,15 | 70,0 04.08.16 02:30 | 52,15 | 70,0 04.08.16 02:40 | 53,15 | 70,0
预期结果(02:00-01:40 = 00:20):
DURATION | START | END ---------+----------------+--------------- 00:20 | 04.08.16 01:40 | 04.08.16 02:00
答案 0 :(得分:3)
您可以使用row_number()
来标识时间段。这是一个孤岛问题。以下返回测量超过阈值的每个周期:
select max(dt) - min(dt) as duration, min(dt), max(dt)
from (select t.*,
row_number() over (order by dt) as seqnum,
row_number() over (partition by (case when measurement > threshold then 1 else 2 end), order by dt) as seqnum_t
from t
) t
where measurement > threshold
group by (seqnum - seqnum_t)
答案 1 :(得分:2)
您可以使用MATCH_RECOGNIZE子句(以及一些其他信息):
WITH t (DT, MEASUREMENT, THRESHOLD) AS (
SELECT TO_DATE('01:10', 'hh24:mi'), 60.5 , 70 FROM dual UNION ALL
SELECT TO_DATE('01:20', 'hh24:mi'), 65.5 , 70 FROM dual UNION ALL
SELECT TO_DATE('01:30', 'hh24:mi'), 68.1 , 70 FROM dual UNION ALL
SELECT TO_DATE('01:40', 'hh24:mi'), 70.1 , 70 FROM dual UNION ALL
SELECT TO_DATE('01:50', 'hh24:mi'), 70.1 , 70 FROM dual UNION ALL
SELECT TO_DATE('02:00', 'hh24:mi'), 70.75 , 70 FROM dual UNION ALL
SELECT TO_DATE('02:10', 'hh24:mi'), 53.5 , 70 FROM dual UNION ALL
SELECT TO_DATE('02:20', 'hh24:mi'), 50.15 , 70 FROM dual UNION ALL
SELECT TO_DATE('02:30', 'hh24:mi'), 52.15 , 70 FROM dual UNION ALL
SELECT TO_DATE('02:40', 'hh24:mi'), 53.15 , 70 FROM dual)
SELECT MEASUREMENT_MAX, match_num, FIRST_DT, LAST_DT, (LAST_DT-FIRST_DT)*24*60 AS DURATION
FROM t
MATCH_RECOGNIZE (
ORDER BY DT
MEASURES
FINAL MAX(MEASUREMENT) AS MEASUREMENT_MAX,
MATCH_NUMBER() AS match_num,
FINAL LAST(DT) AS LAST_DT,
FINAL FIRST(DT) AS FIRST_DT
PATTERN (a+)
DEFINE
a AS MEASUREMENT > THRESHOLD);
MEASUREMENT_MAX match_num FIRST_DT LAST_DT DURATION
70.75 3 01.06.2018 01:40:00 01.06.2018 02:00:00 20
答案 2 :(得分:0)
使用row_number分析函数:
xmltable
输出:
...
SELECT d.dname, e.ename, e.empno
FROM dept d
LEFT OUTER JOIN
(
SELECT x.*
FROM empdata e_data
CROSS JOIN
xmltable (
'office/emp'
PASSING e_data.xcol
COLUMNS deptno NUMBER (28, 0) PATH 'deptno',
ename VARCHAR2 (10) PATH 'ename',
empno NUMBER (28, 0) PATH 'empno') x
) e
ON d.deptno = e.deptno;
DNAME ENAME EMPNO
---------- ---------- ----------
Accounting Abraham 1
Accounting Alexander 2
Broking Benjamin 3
Broking Bradley 4
HR
您的查询将是:
SQL> WITH measurements (DT, MEASUREMENT, THRESHOLD) AS (
2 select to_date('04.08.16 01:10', 'DD.MM.YY HH24:MI'), 60.5, 70.0 from dual union all
3 select to_date('04.08.16 01:20', 'DD.MM.YY HH24:MI'), 65.5, 70.0 from dual union all
4 select to_date('04.08.16 01:30', 'DD.MM.YY HH24:MI'), 68.1, 70.0 from dual union all
5 select to_date('04.08.16 01:40', 'DD.MM.YY HH24:MI'), 70.1, 70.0 from dual union all
6 select to_date('04.08.16 01:50', 'DD.MM.YY HH24:MI'), 70.1, 70.0 from dual union all
7 select to_date('04.08.16 02:00', 'DD.MM.YY HH24:MI'), 70.75, 70.0 from dual union all
8 select to_date('04.08.16 02:10', 'DD.MM.YY HH24:MI'), 53.5, 70.0 from dual union all
9 select to_date('04.08.16 02:20', 'DD.MM.YY HH24:MI'), 50.15, 70.0 from dual union all
10 select to_date('04.08.16 02:30', 'DD.MM.YY HH24:MI'), 52.15, 70.0 from dual union all
11 select to_date('04.08.16 02:40', 'DD.MM.YY HH24:MI'), 53.15, 70.0 from dual),
12 ---------------------
13 ---- end of data preparation
14 ---------------------
15 calculated_values AS (
16 SELECT DT,
17 MEASUREMENT,
18 THRESHOLD,
19 row_number() OVER (ORDER BY dt) - row_number() OVER (PARTITION BY CASE WHEN MEASUREMENT > THRESHOLD THEN 1 ELSE 0 END ORDER BY dt) rn,
20 CASE WHEN MEASUREMENT > THRESHOLD THEN 1 ELSE 0 END threshold_flag
21 FROM measurements)
22 SELECT cast(numtodsinterval(MAX(dt)-MIN(dt), 'DAY') AS INTERVAL DAY(0) TO SECOND(0)) AS duration,
23 MIN(dt) AS "START",
24 MAX(dt) AS "END"
25 FROM calculated_values
26 WHERE threshold_flag > 0
27 GROUP BY rn;
答案 3 :(得分:0)
您不需要使用两个row_number,可以通过累积方法直接使用它:
select max(dt) - min(dt) as duration, min(dt), max(dt)
from (select *, row_number() over (order by dt) as seq,
sum(case when measurement > threshold then 1 else 0 end) over(order by dt) as grp
from table
) t
where measurement > threshold
group by (seq - grp);