【SQL逻辑】groupings sets场景应用

背景

今天遇到一个SQL场景有如下表table,每个订单对应买了多个品类(品类数枚举值只有(A、B、C))。

order_idcate
001A
001B
001C
002A
002B
003A
004B
004D

需要提前统计,各个类型品类组合下的下单量(对订单去重),结果如下

cateorder_qty
A3
B3
C1
D1
AB4
AC3
AD4
BC3
BD3
CD2
ABC4
ACD4
ACD4
BCD3
ABCD4

方案

  • 建表写数据
create table tmp (
	order_id String
	, cate String
)comment '测试表'
row format delimited fields terminated by ',' stored as textfile


  • 方案一
    一开始想到的,这种场景,union all一定能成,所以简单粗暴。如下,虽然代码冗余,但是确实很直白。
select cate,count(distinct order_id) from tmp group by cate
union all
select 'AB',count(distinct order_id) from tmp where cate in ('A','B')
union all
select 'AC',count(distinct order_id) from tmp where cate in ('A','C')
union all
select 'AD',count(distinct order_id) from tmp where cate in ('A','D')
union all
select 'BC',count(distinct order_id) from tmp where cate in ('B','C')
union all
select 'BD',count(distinct order_id) from tmp where cate in ('B','D')
union all
select 'CD',count(distinct order_id) from tmp where cate in ('C','D')
union all
select 'ABC',count(distinct order_id) from tmp where cate in ('A','B','C')
union all
select 'ABD',count(distinct order_id) from tmp where cate in ('A','B','D')
union all
select 'BCD',count(distinct order_id) from tmp where cate in ('B','C','D')
union all
select 'ABCD',count(distinct order_id) from tmp where cate in ('A','B','C','D')
  • 方案二
    后面灵机一动,可以用case when+grouping sets
with tmp as (
  select order_id,cate
  ,case when cate = 'A' then '1' else '0' end as is_A
  ,case when cate = 'B' then '1' else '0' end as is_B
  ,case when cate = 'C' then '1' else '0' end as is_C
  ,case when cate = 'D' then '1' else '0' end as is_D
   from tmp
), base as (
  select is_A,is_B,is_C,is_D,grouping__id,count(distinct order_id) as qty from tmp
  group by is_A,is_B,is_C,is_D
  grouping sets(
    (is_A,is_B,is_C), -- D的聚合
    (is_A,is_B,is_D), -- C的聚合
    (is_A,is_C,is_D), -- B的聚合
    (is_B,is_C,is_D), -- A的聚合
    (is_A,is_B), -- CD的聚合
    (is_A,is_C), -- BD的聚合
    (is_A,is_D), -- BC的聚合
    (is_B,is_C), -- AD的聚合
    (is_B,is_D), -- AC的聚合
    (is_C,is_D), -- AB的聚合
    (is_A), -- BCD的聚合
    (is_B), -- ACD的聚合
    (is_C), -- ABD的聚合
    (is_D), -- ABC的聚合
    ()      -- ABCD的聚合
  )
)

select
case when grouping__id = 15 then 'ABCD'
     when grouping__id = 14 then 'ABC'
     when grouping__id = 13 then 'ABD'
     when grouping__id = 12 then 'AB'
     when grouping__id = 11 then 'ACD'
     when grouping__id = 10 then 'AC'
     when grouping__id = 9 then 'AD'
     when grouping__id = 8 then 'A'
     when grouping__id = 7 then 'BCD'
     when grouping__id = 6 then 'BC'
     when grouping__id = 5 then 'BD'
     when grouping__id = 4 then 'B'
     when grouping__id = 3 then 'CD'
     when grouping__id = 2 then 'C'
     when grouping__id = 1 then 'D'
     else null end as val
,qty
from base
where 
-- 过滤带1的都不是我们需要的结果
concat(coaLesce(is_A,''),Coalesce(is_B,''),coalesce(is_C,''),coalesce(is_D,'')) = '0000'
or concat(coaLesce(is_A,''),Coalesce(is_B,''),coalesce(is_C,''),coalesce(is_D,'')) = '000'
or concat(coaLesce(is_A,''),Coalesce(is_B,''),coalesce(is_C,''),coalesce(is_D,'')) = '00'
or concat(coaLesce(is_A,''),Coalesce(is_B,''),coalesce(is_C,''),coalesce(is_D,'')) = '0'
or concat(coaLesce(is_A,''),Coalesce(is_B,''),coalesce(is_C,''),coalesce(is_D,'')) = ''
order by val

结果如下:

valqty
A3
AB4
ABC4
ABCD4
AC3
ACD4
ACD4
AD4
B3
BC3
BCD3
BD3
C1
CD2
D1

总结

groupings sets 的多维度聚合,通过分析,其实可以玩出很多花样,之后有其他场景再总结。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值