sql- sum if() 用法举例

题目:

从订单明细表(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,获取所有用户,商品信息
sql 复制代码
     select

            od.order_id,

            sku_id,

            user_id

     from  order_detail od

     join  order_info oi  

     on oi.order_id = od.order_id               t1
2.按照用户,商品,分组,统计用户购买单种商品的数量
sql 复制代码
    select 

         user_id,

          sku_id,

          count(*) ct

    from t1

    group by user_id,sku_id                    t2
3.根据用户购买每种商品的数量,筛选购买1,2但是没有购买3的商品。
sql 复制代码
    select

            user_id

     from t2

    where sku_id in (1,2) and user_id not in 

   (select

            user_id

    from t2

    where sku_id = 3)

   group by user_id

    
4.拼接最终SQL
sql 复制代码
with tmp1 as (
  select
      sku_id,
      user_id,
      count(*) ct
  from 
  (
  select
      od.order_id,
      sku_id,
      user_id
  from 
      order_detail od
  join 
      order_info oi
  on 
      od.order_id = oi.order_id
  )t1
  group by sku_id,user_id
)

select
	user_id
from 
   tmp1
where sku_id in (1,2)
and user_id not in
(select
	user_id
from tmp1
where sku_id = 3)
group by user_id

2.使用sum if

1. 将订单表与订单明细表进行join,获取所有用户,商品信息
sql 复制代码
order_detail od
      join order_info oi on od.order_id = oi.order_id
2.按照用户,商品,分组,统计用户-商品的信息
sql 复制代码
    SELECT
      oi.user_id,
      od.sku_id
    from t1
    group by
      oi.user_id,
      od.sku_id
3.根据用户分组,使用sum..if.. 统计购买1,2但是没有购买3的用户。

不难看出,使用sum if 可以统计购买1,2的用户。若不符合过滤条件,将不会展示用户信息

同时,having后面直接添加聚合函数进行聚合,简化了在select语句写聚合函数的过程。

sql 复制代码
SELECT
  user_id
from t3
group by
  user_id
having
  sum(if (sku_id = 3, -3, if (sku_id in (1, 2), 1, 0))) = 2
4.最终SQL
sql 复制代码
SELECT
  user_id
from
  (
    SELECT
      oi.user_id,
      od.sku_id
    from
      order_detail od
      join order_info oi on od.order_id = oi.order_id
    group by
      oi.user_id,
      od.sku_id
  ) t
group by
  user_id
having
  sum(if (sku_id = 3, -3, if (sku_id in (1, 2), 1, 0))) = 2

------ 第二种是某位大佬写的,更推荐第二种写法,不禁肃然起敬。

相关推荐
RestCloud3 小时前
揭秘 CDC 技术:让数据库同步快人一步
数据库·api
得物技术6 小时前
MySQL单表为何别超2000万行?揭秘B+树与16KB页的生死博弈|得物技术
数据库·后端·mysql
可涵不会debug10 小时前
【IoTDB】时序数据库选型指南:工业大数据场景下的技术突围
数据库·时序数据库
ByteBlossom10 小时前
MySQL 面试场景题之如何处理 BLOB 和CLOB 数据类型?
数据库·mysql·面试
麦兜*10 小时前
MongoDB Atlas 云数据库实战:从零搭建全球多节点集群
java·数据库·spring boot·mongodb·spring·spring cloud
Slaughter信仰10 小时前
深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)第十章知识点问答(10题)
java·jvm·数据库
麦兜*10 小时前
MongoDB 在物联网(IoT)中的应用:海量时序数据处理方案
java·数据库·spring boot·物联网·mongodb·spring
-Xie-11 小时前
Mysql杂志(十六)——缓存池
数据库·mysql·缓存