sql查询:pivot但具有不同的计数或行

时间:2016-08-30 06:39:16

标签: sql oracle pivot

构造查询以将行收集到像pivot这样的列中的最佳变体是什么,但没有聚合,每列中可能有多行?

示例数据:

id, parent_fk, month, quantity
10, 1111, 'jan', 21
11, 1111, 'jan', 24
12, 1111, 'feb', 12

13, 2222, 'jan', 3 
14, 2222, 'feb', 4
15, 2222, 'mar', 5

16, 3333, 'feb', 77
17, 3333, 'feb', 88
16, 3333, 'mar', 99

每个月可能包含不同的行数。我必须把它们放在一边,并由heigths证明。 我想将这些数据显示为:

parent_fk, jan, feb, mar
1111,    21, 12, __
1111,    24, __, __
2222,     3,  4,  5
3333,    __, 77, 99
3333,    __, 88, __

目前我有这样一个不优雅的查询(在每个月内使用row_number在分区上创建排序,并按此顺序加入所有monthes):

select
    nvl(JAN.parent_fk, nvl(FEB.parent_fk, nvl(MAR.parent_fk, -1))) calc_parent_fk,
    JAN.quantity jan, 
    FEB.quantity feb, 
    MAR.quantity mar
 from
    (select id, parent_fk, quantity, 
    row_number() OVER (PARTITION BY parent_fk, mnth order by id) "RN" 
    from T_MONTH_DATA 
    where mnth = 'jan') JAN 
full join
    (select id, parent_fk, quantity, 
    row_number() OVER (PARTITION BY parent_fk, mnth order by id) "RN" 
    from T_MONTH_DATA 
    where mnth = 'feb') FEB
    on JAN.parent_fk = FEB.parent_fk and JAN.RN = FEB.RN
full join
    (select id, parent_fk, quantity, 
    row_number() OVER (PARTITION BY parent_fk, mnth order by id) "RN" 
    from T_MONTH_DATA 
    where mnth = 'mar') MAR
    on FEB.parent_fk = MAR.parent_fk and FEB.RN = MAR.RN
order by 1

是否有更简单的方式来呈现此类数据? 如何获得结果parent_fk? (我使用嵌套的NVL,因为我不知道哪个monthes包含最多行,而所有其他monthes都有null)。

1 个答案:

答案 0 :(得分:2)

在Oracle 11g中使用pivot子句和函数row_number(),如下所示:

select parent_fk, jan, feb, mar 
  from ( 
    select row_number() over (partition by mnth, parent_fk order by id) rn, 
           parent_fk, mnth, quantity 
      from t_month_data )
  pivot (sum(quantity) for mnth in ('jan' jan, 'feb' feb, 'mar' mar))
  order by parent_fk

测试数据和输出:

create table t_month_data (id number(4), parent_fk number(4), 
                           mnth varchar2(3), quantity number(6));

insert into t_month_data values (10, 1111, 'jan', 21);
insert into t_month_data values (11, 1111, 'jan', 24);
insert into t_month_data values (12, 1111, 'feb', 12);
insert into t_month_data values (13, 2222, 'jan',  3);
insert into t_month_data values (14, 2222, 'feb',  4);
insert into t_month_data values (15, 2222, 'mar',  5);
insert into t_month_data values (16, 3333, 'feb', 77);
insert into t_month_data values (17, 3333, 'feb', 88);
insert into t_month_data values (16, 3333, 'mar', 99);

PARENT_FK        JAN        FEB        MAR
--------- ---------- ---------- ----------
     1111         21         12 
     1111         24            
     2222          3          4          5
     3333                    77         99
     3333                    88