Oracle按时间窗口选择总和

时间:2014-05-15 09:22:50

标签: sql oracle select

让我们假设我们有以下格式和数据的ORACLE表:

TIMESTAMP                 MESSAGENO              ORGMESSAGE                           
------------------------- ---------------------- -------------------------------------
27.04.13                  1                      START PERIOD  
27.04.13                  3                      10
27.04.13                  4                      5
28.04.13                  5                      6
28.04.13                  3                      20
29.04.13                  4                      25
29.04.13                  5                      26
30.04.13                  2                      END PERIOD
30.04.13                  1                      START PERIOD  
01.05.13                  3                      10
02.05.13                  4                      15
02.05.13                  5                      16
03.05.13                  3                      30
03.05.13                  4                      35
04.05.13                  5                      36
05.05.13                  2                      END PERIOD

我想为MESSAGENO分组的所有时段(START PERIOD和END PERIOD之间的窗口)选择所有ORGMESSAGE的总和。

Exapmle输出将是:

PERIOD START  PERIOD END   MESSAGENO SUM 
------------ ------------- --------  ----
27.04.13     30.04.13        3        25
27.04.13     30.04.13        4        30
27.04.13     30.04.13        5        32
30.04.13     05.05.13        3        45
30.04.13     05.05.13        4        50
30.04.13     05.05.13        5        52

我猜测使用ORACLE Analityc函数woulde是合适的,但实际上不知道如何以及从何处开始。 提前感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

如果我们假设期间开始和结束匹配,那么找到匹配消息的简单方法是计算先前的启动次数。这是一个累积总和,在Oracle中很容易。其余的只是聚合:

select min(timestamp) as periodstart, max(timestamp) as periodend, messageno, count(*)
from (select om.*,
             sum(case when messageno = 1 then 1 else 0 end) over (order by timestamp) as grp
      from orgmessages om
     ) om
where messageno not in (1, 2)
group by grp, messageno;

请注意,此方法(与其他方法一样)确实希望时间戳在每条记录上都是唯一的。在提供的数据中,这些解决方案将起作用。但是如果你在同一天有多个开始和结束,假设timestamp只有日期,那么它们都不起作用。

答案 1 :(得分:0)

请尝试这一个,将rrr替换为您的表名

select periodstart, periodend, messageno, sum(to_number(orgmessage)) s
from (select TIMESTAMP periodstart,
             (select min (TIMESTAMP) from rrr r2 where orgmessage = 'END PERIOD' and r2.TIMESTAMP > r.TIMESTAMP) periodend
      from rrr r
      where orgmessage = 'START PERIOD'
) borders, rrr r
where r.TIMESTAMP between borders.periodstart and borders.periodend 
      and r.orgmessage not in ('END PERIOD', 'START PERIOD')
group by periodstart, periodend, messageno
order by periodstart, periodend, messageno

答案 2 :(得分:0)

首先查找每期开始的所有期末。然后加入你的表格进行分组和总结。

select 
  dates.start_date, 
  dates.end_date, 
  messageno, 
  sum(to_number(orgmessage)) as period_sum
from mytable
join
(
  select start_dates.timestmp as start_date, min(end_dates.timestmp) as end_date
  from (select * from mytable where orgmessage = 'START PERIOD') start_dates
  join (select * from mytable where orgmessage = 'END PERIOD') end_dates
    on start_dates.timestmp < end_dates.timestmp
  group by start_dates.timestmp
) dates on mytable.timestmp between dates.start_date and dates.end_date
where mytable.orgmessage not like '%PERIOD%'
group by dates.start_date, dates.end_date, messageno
order by dates.start_date, dates.end_date, messageno;

SQL小提琴:http://www.sqlfiddle.com/#!4/365de/15