如何获得此
的优化查询date_one | date_two
------------------------
01.02.1999 | 31.05.2003
01.01.2004 | 01.01.2010
02.01.2010 | 10.10.2011
11.10.2011 | (null)
我需要得到这个
date_one | date_two | group
------------------------------------
01.02.1999 | 31.05.2003 | 1
01.01.2004 | 01.01.2010 | 2
02.01.2010 | 10.10.2011 | 2
11.10.2011 | (null) | 2
组号分配如下。按行date_one
升序排序。第一行获得group = 1
。然后,如果date_one
是前一行date_two
之后的日期,那么对于每一行,group
数字与previous
行中的相同,否则增加1
答案 0 :(得分:1)
您可以使用left join
和累积总和来执行此操作:
select t.*, sum(case when tprev.date_one is null then 1 else 0 end) over (order by t.date_one) as grp
from t left join
t tprev
on t.date_one = tprev.date_two + 1;
我们的想法是找到差距开始的位置(使用左连接),然后对这些开头进行累积求和以定义组。
如果你想要更加不可思议,你可以写成:
select t.*,
count(*) over (order by t.date_one) - count(tprev.date_one) over (order by t.date_one) as grp
from t left join
t tprev
on t.date_one = tprev.date_two + 1;
答案 1 :(得分:1)
一种方法是使用窗口功能:
select
date_one,
date_two,
sum(x) over (order by date_one) grp
from (
select
t.*,
case when
lag(date_two) over (order by date_one) + 1 =
date_one then 0 else 1 end x
from t
);
它使用分析函数lag
从最后一行找到date_two,并检查它是否继续使用此行中的date_one(按date_one的递增顺序)。
lag(date_two) over (order by date_one)
(在下面的解释中,当我说第一行,下一行,上一行或最后一行时,它基于date_one的增加顺序,结尾为空值)
上面的产生为第一行产生NULL
,因为在它之前没有行来获取date_two,而前一行的date_two用于后续行。
case when
lag(date_two)
over (order by date_one) + 1 = date_one then 0
else 1 end
因为,滞后为第一行产生NULL
(因为NULL = anything
表达式总是最终计算为false),case的输出将为1.
对于更多的行,将进行类似的检查以在查询输出中生成新列x
,当前一行的date_two不与此行的date_one连续时,该列的值为1.
最后,我们可以在x
上进行增量求和,以找到所需的组值。请参阅下面的x值以了解:
SQL> with t (date_one,date_two) as (
2 select to_date('01.02.1999','dd.mm.yyyy'),to_date('31.05.2003','dd.mm.yyyy') from dual union
all
3 select to_date('01.01.2004','dd.mm.yyyy'),to_date('01.01.2010','dd.mm.yyyy') from dual union
all
4 select to_date('02.01.2010','dd.mm.yyyy'),to_date('10.10.2011','dd.mm.yyyy') from dual union
all
5 select to_date('11.10.2011','dd.mm.yyyy'),null from dual
6 )
7 select
8 date_one,
9 date_two,
10 x,
11 sum(x) over (order by date_one) grp
12 from (
13 select
14 t.*,
15 case when
16 lag(date_two) over (order by date_one) + 1 =
17 date_one then 0 else 1 end x
18 from t
19 );
DATE_ONE DATE_TWO X GRP
--------- --------- ---------- ----------
01-FEB-99 31-MAY-03 1 1
01-JAN-04 01-JAN-10 1 2
02-JAN-10 10-OCT-11 0 2
11-OCT-11 0 2
SQL>