订阅更新

苹果和桔子每天的销量差:不要依赖行的顺序

SQL 实战 123 题 · 第 110 题 中等 约 2 分钟读完

LeetCode 1445 · 条件聚合、带符号求和、窗口函数的确定性

本文目录
  1. 面试怎么回答
  2. 题意
  3. 表结构
  4. 思路
  5. 参考解法
  6. 易错点

面试怎么回答

按 sale_date 分组,SUM(CASE WHEN fruit = 'apples' THEN sold_num ELSE -sold_num END)。不用 LEAD,因为窗口里不写 ORDER BY 时行序不确定,苹果的下一行未必是桔子;条件求和不依赖顺序,某天缺一种水果也能算对。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

题意

销售表记录每天苹果和桔子各卖了多少(每天两种水果各一行)。输出每天苹果销量减桔子销量的差,按日期排序。

表结构

  • Sales:sale_date、fruit(apples / oranges)、sold_num;(sale_date, fruit) 为主键

思路

最稳妥的写法是按日期分组,苹果记正、桔子记负,求和就是差值。原解法用 LEAD 在同一天的两行之间取「下一行」,但窗口里没写 ORDER BY,同一天两行谁在前不确定,苹果那行的「下一行」不一定是桔子,结果可能是错的。

参考解法

select  sale_date,sold_num-ld diff
from 
(
select sale_date,sold_num , fruit ,lead(sold_num ,1,null) over(partition by  sale_date ) ld
from Sales
)t1
where fruit='apples'

另一种写法:按日期分组的带符号求和

SELECT sale_date, SUM(IF(fruit = 'apples', sold_num, -sold_num)) AS diff
FROM Sales
GROUP BY sale_date
ORDER BY sale_date

易错点

  • 窗口函数没有 ORDER BY 时,分区内行的顺序是不确定的,LEAD / LAG 的结果也就不确定。
  • 某天只卖了一种水果时,LEAD 写法会得到 NULL,条件求和写法能正确算出差值。
刷题进度保存在当前浏览器