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

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

相关推荐
晋阳十二夜5 小时前
【压力测试之_Jmeter链接Oracle数据库链接】
数据库·oracle·压力测试
GDAL6 小时前
Node.js v22.5+ 官方 SQLite 模块全解析:从入门到实战
数据库·sqlite·node.js
DCTANT7 小时前
【原创】国产化适配-全量迁移MySQL数据到OpenGauss数据库
java·数据库·spring boot·mysql·opengauss
AI、少年郎9 小时前
Oracle 进阶语法实战:从多维分析到数据清洗的深度应用(第四课)
数据库·oracle
赤橙红的黄9 小时前
自定义线程池-实现任务0丢失的处理策略
数据库·spring
DataGear10 小时前
如何在DataGear 5.4.1 中快速制作SQL服务端分页的数据表格看板
javascript·数据库·sql·信息可视化·数据分析·echarts·数据可视化
weixin_4383354010 小时前
分布式锁实现方式:基于Redis的分布式锁实现(Spring Boot + Redis)
数据库·redis·分布式
码不停蹄的玄黓10 小时前
MySQL Undo Log 深度解析:事务回滚与MVCC的核心功臣
数据库·mysql·undo log·回滚日志
Qdgr_10 小时前
价值实证:数字化转型标杆案例深度解析
大数据·数据库·人工智能
数据狐(DataFox)10 小时前
SQL参数化查询:防注入与计划缓存的双重优势
数据库·sql·缓存