2

我正在寻找一个需要连续几天的查询,并将它们组合在一起,具体取决于它们是否真的连续以及属于该日期的值。我正在使用 Oracle 版本 11g。

这是一些示例数据:

date          value
2012-01-01    2000
2012-01-02    2000 //(there is no data for Jan 03 for example)
2012-01-04    2000
2012-01-05    5000
2012-01-06    5000
2012-01-07    5000
2012-01-08    2000
2012-01-09    2000
2012-01-10    2000

(这是相当大的查询的结果)

我正在寻找的会将这些日子组合在一起,如下所示:

from_date   to_date     value
2012-01-01  2012-01-02  2000
2012-01-04  2012-01-04  2000
2012-01-05  2012-01-07  5000
2012-01-08  2012-01-10  2000

我们确实设法制定了一个执行我想要的查询,但这不是一种非常有效的方式,我很确定存在更好/更优雅的东西。这就是我现在正在使用的:

with temp_table as (
select a.pk_date DATE1, c.pk_date DATE2, a.volume VOL1
from dm_2203 a, dm_2203 c
where a.volume = c.volume
  and a.pk_date <= c.pk_date
  and not exists (select 1 from dm_2203 b
                  where a.volume = b.volume
                    and a.pk_date = b.pk_date+1)
  and not exists (select 1 from dm_2203 d
                  where c.volume = d.volume
                    and c.pk_date = d.pk_date-1)  )
select * from temp_table y
where date2-date1+1 = (select count(*)
                       from dm_2203 z
                       where z.pk_date between y.date1 and y.date2
                         and y.vol1 = z.volume)
order by 1;

有没有人知道如何在没有所有连接的情况下更快地做到这一点?谢谢!

4

2 回答 2

3

我认为这应该有效,而且效率也相当高(它应该只上桌一次)

create table t ( d date, v number);

insert into t values (trunc(sysdate), 100);
insert into t values (trunc(sysdate+2), 100);
insert into t values (trunc(sysdate+3), 100);
insert into t values (trunc(sysdate+4), 100);
insert into t values (trunc(sysdate+5), 200);
insert into t values (trunc(sysdate+6), 200);
insert into t values (trunc(sysdate+7), 200);
insert into t values (trunc(sysdate+8), 100);

select min(d), max(d), v
from (
    select d, v, 
        sum( gc) over (partition by v order by d) g
    from (
        select d, v, 
            (case (d - lag(d) over ( partition by v order by d) )
                when 1 then 0
                else 1
             end) gc
        from t
    )
) group by v, g
order by min(d), v

Note that if you want to run the logic in an efficient way on a subset of your data, you should add the where clause in the inner most select. Otherwise oracle will have problems to use any index.

于 2012-03-22T15:04:46.670 回答
0

尝试:

with cte as (
select pk_date from_date, pk_date to_date, volume
from dm_2203 d
where not exists
(select null from dm_2203 e 
 where d.volume = e.volume and d.pk_date-1 = e.pk_date)
union all
select c.pk_date from_date, d.pk_date to_date, c.volume
from cte c
join dm_2203 d on d.volume = c.volume and d.pk_date = c.pk_date+1)
select from_date, max(to_date) to_date, volume "value"
from cte
group by from_date, volume
于 2012-03-22T14:56:56.430 回答