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

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

相关推荐
在未来等你18 分钟前
SQL进阶之旅 Day 21:临时表与内存表应用
sql·mysql·postgresql·database·temporary-table·memory-table·sql-optimization
敖云岚1 小时前
【Redis】分布式锁的介绍与演进之路
数据库·redis·分布式
zhuiQiuMX1 小时前
分享今天做的力扣SQL题
sql·算法·leetcode
LUCIAZZZ1 小时前
HikariCP数据库连接池原理解析
java·jvm·数据库·spring·springboot·线程池·连接池
我在北京coding2 小时前
300道GaussDB(WMS)题目及答案。
数据库·gaussdb
小Tomkk2 小时前
阿里云 RDS mysql 5.7 怎么 添加白名单 并链接数据库
数据库·mysql·阿里云
明月醉窗台3 小时前
qt使用笔记二:main.cpp详解
数据库·笔记·qt
沉到海底去吧Go3 小时前
【图片自动识别改名】识别图片中的文字并批量改名的工具,根据文字对图片批量改名,基于QT和腾讯OCR识别的实现方案
数据库·qt·ocr·图片识别自动改名·图片区域识别改名·pdf识别改名
老纪的技术唠嗑局4 小时前
重剑无锋,大巧不工 —— OceanBase 中的 Nest Loop Join 使用技巧分享
数据库·sql
未来之窗软件服务4 小时前
JAVASCRIPT 前端数据库-V6--仙盟数据库架构-—-—仙盟创梦IDE
数据库·数据库架构·仙盟创梦ide·东方仙盟·东方仙盟数据库