如何将多个组转换为二进制分组?

时间:2016-08-28 02:42:24

标签: sql oracle oracle11g analytics

我想报告“PINK”与所有其他颜色的数量

with gumdrops_detail as
(
select 1 as customer_id, 'PINK' as gumdrop_color, 400 as gumdrop_volume from dual union all
select 1 as customer_id, 'PINK' as gumdrop_color, 300 as gumdrop_volume from dual union all
select 1 as customer_id, 'BLUE' as gumdrop_color, 500 as gumdrop_volume from dual union all
select 1 as customer_id, 'BLUE' as gumdrop_color, 600 as gumdrop_volume from dual union all
select 1 as customer_id, 'SNOT' as gumdrop_color, 300 as gumdrop_volume from dual union all
select 1 as customer_id, 'SNOT' as gumdrop_color, 100 as gumdrop_volume from dual union all
select 2 as customer_id, 'PINK' as gumdrop_color, 400 as gumdrop_volume from dual union all
select 2 as customer_id, 'PINK' as gumdrop_color, 300 as gumdrop_volume from dual union all
select 2 as customer_id, 'BLUE' as gumdrop_color, 500 as gumdrop_volume from dual union all
select 2 as customer_id, 'BLUE' as gumdrop_color, 600 as gumdrop_volume from dual union all
select 3 as customer_id, 'SNOT'  as gumdrop_color, 300 as gumdrop_volume from dual union all
select 3 as customer_id, 'ECRU' as gumdrop_color, 100 as gumdrop_volume from dual
)
select distinct customer_id,
       gumdrop_color,
       sum(gumdrop_volume) over (partition by customer_id,
                                              gumdrop_color) as vol_by_color,
       sum(case gumdrop_color
            when 'PINK' then gumdrop_volume
            else             gumdrop_volume
            end) over (partition by customer_id,
                                    gumdrop_color) as vol_by_pink_non_pink 
from gumdrops_detail
order by customer_id

期望的结果

ID  COLOR   TOTVOL
1   PINK     700
1   NONPINK 1500
2   PINK     700
2   NONPINK 1100
3   PINK       0 --Its OK if this row doesn't return...
3   NONPINK  400

3 个答案:

答案 0 :(得分:3)

with gumdrops_detail as
(
 ...
)
select customer_id, B.color,
       sum( decode(B.color,
                   decode(gumdrop_color,'PINK','PINK','NONPINK'), gumdrop_volume, 0))
  from gumdrops_detail,
       (select 'PINK' as color from DUAL union select 'NONPINK' from DUAL) B
 group by customer_id, B.color
 order by customer_id, B.color desc

结果:

1   PINK    700
1   NONPINK 1500
2   PINK    700
2   NONPINK 1100
3   PINK    0
3   NONPINK 400

如果ZERO不存在' PINK'不需要:

with gumdrops_detail as
(
 ...
)
select customer_id, decode(gumdrop_color,'PINK','PINK','NONPINK') color,sum(gumdrop_volume)
  from gumdrops_detail
 group by customer_id, decode(gumdrop_color,'PINK','PINK','NONPINK')
 order by 1,2 desc

P.S。:decode(B.color,decode(gumdrop_color,'PINK','PINK','NONPINK'),gumdrop_volume, 0)可以表示为:

case B.color
when (
      case gumdrop_color when 'PINK' then 'PINK'
                         else 'NONPINK'
      end
     )
then gumdrop_volume
else 0
end

答案 1 :(得分:1)

不是最有效的解决方案,但它很容易理解。

with gumdrops_detail as
(
........
)
select * from (
select customer_id as id,
       'PINK' as color,
       sum(case gumdrop_color when 'PINK' then gumdrop_volume else 0 end) as total_volume
from   gumdrops_detail
group by customer_id
union all
select customer_id as id,
       'NON-PINK' as color,
       sum(case gumdrop_color when 'PINK' then 0 else gumdrop_volume end) as total_volume
from   gumdrops_detail
group by customer_id
)
order by id, case color when 'PINK' then 0 else 1 end
;

        ID COLOR                               TOTAL_VOLUME
---------- -------- ---------------------------------------
         1 PINK                                         700
         1 NON-PINK                                    1500
         2 PINK                                         700
         2 NON-PINK                                    1100
         3 PINK                                           0
         3 NON-PINK                                     400

 6 rows selected 

更高级(也许更高效)的解决方案使用unpivot - 自Oracle版本11以来可用。

select id, color, total_volume from (
select customer_id as id,
       sum(case gumdrop_color when 'PINK' then gumdrop_volume else 0 end) as pink,
       sum(case gumdrop_color when 'PINK' then 0 else gumdrop_volume end) as non_pink
from   gumdrops_detail
group by customer_id
)
unpivot (total_volume for color in (pink as 'PINK', non_pink as 'NON_PINK'))
order by id, case color when 'PINK' then 0 else 1 end
;

答案 2 :(得分:0)

如果你愿意将粉红色与非粉红色分成单独的列,那么这个 查询可能是合适的。

select distinct customer_id,
       sum(gumdrop_volume) over (partition by customer_id) as cust_volume,

       sum(case gumdrop_color 
            when 'PINK' then gumdrop_volume
            else 0
            end) over (partition by customer_id) as pink_v,

       sum(case gumdrop_color 
            when 'PINK' then 0
            else gumdrop_volume
            end) over (partition by customer_id) as non_pink_v
from gumdrops_detail  
order by customer_id

<强>结果

 ID   VOL  PINK_V  NON-PINK_V
     1 2200   700        1500
     2 1800   700        1100
     3  400     0         400