题目:
从订单明细表(order_detail)中查询出所有购买过商品1和商品2,但是没有购买过商品3的用户
订单表 order_info
order_id (订单id) | user_id (用户id) | create_date (下单日期) | total_amount (订单金额) |
---|---|---|---|
1 | 101 | 2021-09-30 | 29000.00 |
10 | 103 | 2020-10-02 | 28000.00 |
订单明细表 order_detail
order_detail_id(订单明细id) | order_id(订单id) | sku_id(商品id) | create_date(下单日期) | price(商品单价) | sku_num(商品件数) |
---|---|---|---|---|---|
1 | 1 | 1 | 2021-09-30 | 2000.00 | 2 |
2 | 1 | 3 | 2021-09-30 | 5000.00 | 5 |
22 | 10 | 4 | 2020-10-02 | 6000.00 | 1 |
23 | 10 | 5 | 2020-10-02 | 500.00 | 24 |
24 | 10 | 6 | 2020-10-02 | 2000.00 | 5 |
计算逻辑
1.使用差集
1. 将订单表与订单明细表进行join,获取所有用户,商品信息
selectod.order_id,sku_id,user_idfrom order_detail odjoin order_info oi on oi.order_id = od.order_id t1
2.按照用户,商品,分组,统计用户购买单种商品的数量
select user_id,sku_id,count(*) ctfrom t1group by user_id,sku_id t2
3.根据用户购买每种商品的数量,筛选购买1,2但是没有购买3的商品。
selectuser_idfrom t2where sku_id in (1,2) and user_id not in (selectuser_idfrom t2where sku_id = 3)group by user_id
4.拼接最终SQL
with tmp1 as (selectsku_id,user_id,count(*) ctfrom (selectod.order_id,sku_id,user_idfrom order_detail odjoin order_info oion od.order_id = oi.order_id)t1group by sku_id,user_id
)selectuser_id
from tmp1
where sku_id in (1,2)
and user_id not in
(selectuser_id
from tmp1
where sku_id = 3)
group by user_id
2.使用sum if
1. 将订单表与订单明细表进行join,获取所有用户,商品信息
order_detail odjoin order_info oi on od.order_id = oi.order_id
2.按照用户,商品,分组,统计用户-商品的信息
SELECToi.user_id,od.sku_idfrom t1group byoi.user_id,od.sku_id
3.根据用户分组,使用sum..if.. 统计购买1,2但是没有购买3的用户。
不难看出,使用sum if 可以统计购买1,2的用户。若不符合过滤条件,将不会展示用户信息
同时,having后面直接添加聚合函数进行聚合,简化了在select语句写聚合函数的过程。
SELECTuser_id
from t3
group byuser_id
havingsum(if (sku_id = 3, -3, if (sku_id in (1, 2), 1, 0))) = 2
4.最终SQL
SELECTuser_id
from(SELECToi.user_id,od.sku_idfromorder_detail odjoin order_info oi on od.order_id = oi.order_idgroup byoi.user_id,od.sku_id) t
group byuser_id
havingsum(if (sku_id = 3, -3, if (sku_id in (1, 2), 1, 0))) = 2
------ 第二种是某位大佬写的,更推荐第二种写法,不禁肃然起敬。