使用group by子句的麻烦

时间:2013-07-24 13:53:04

标签: sql oracle

我的数据如下

A        |  B      | C            |   D          |   E     |  F
217731   |  24856  | 01/01/2006   | 03/31/2007   |  0569   | 972450
217731   |  24856  | 04/01/2007   | 09/30/2008   |  0569   | 972450
217731   |  24856  | 10/01/2008   | 12/31/2008   |  0569   | 972450
217731   |  24856  | 01/01/2009   | 12/31/2009   |  0569   | 972450

217731   |  24856  | 01/01/2010   | 09/30/2011   |  0569   | 318704
217731   |  24856  | 10/01/2011   | 03/04/2012   |  0569   | 318704

217731   |  24856  | 03/05/2012   | 09/30/2012   |  0569   | 972450
217731   |  24856  | 10/01/2012   | 07/31/2013   |  0569   | 972450

我需要输出

 A     |  B     |  C          | D           | F
217731 | 24856  |  01/01/2006 | 31/12/2009  | 972450
217731 | 24856  |  01/01/2010 | 04/03/2012  | 318704
217731 | 24856  |  05/03/2012 | 31/07/2013  | 972450

当我使用group by子句时,我得到如下输出

 A      |  B      | C          | D          | F
217731  | 24856   | 01/01/2006 | 07/31/2013 | 972450
217731  | 24856   | 01/01/2010 | 03/04/2012 | 318704

2 个答案:

答案 0 :(得分:1)

您正在尝试识别具有相同键的不同时间段。幸运的是,Oracle为此提供了大量的分析功能,因为简单的group by是不够的。

以下是查询使用的逻辑。最里面的子查询根据行中的日期和键列创建一个标志(StartPeriod)。这标识新时段开始的时间,因为列C不比前一列D大1天。

然后,StartPeriod累积为累积总和。这会为同一时期内的所有组分配相同的值。此时,有足够的信息可供使用group by。您需要添加其他grping列。

select A, B, MIN(C) as C, MAX(D) as D, E, F
from (select t.*, SUM(StartPeriod) over (partition by A, B, E, F order by C) as grping
      from (select t.*,
                   (case when lag(D) over (partition by A, B, E, F order by C) = C - 1
                         then 0
                         else 1
                    end) as StartPeriod
            from t
           ) t
     ) t
group by A, B, E, F, grping

答案 1 :(得分:0)

如果您的表格不大,请尝试使用此查询:

select A,B,min(C),max(D),F
from
(
select t2.*,
(select count(A) from t where 
  (t.A<>t2.A or t.B<>t2.B or t.F<>t2.F) 
   and t.c<t2.c) Group_n
from t t2
 ) t3
group by A,B,F,Group_n

SQLFiddle demo