题目描述

(通过次数10,129 | 提交次数11,894,通过率85.16%)

表: Sales
+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| sale_date     | date    |
| fruit         | enum    | 
| sold_num      | int     | 
+---------------+---------+
(sale_date,fruit) 是该表主键.
该表包含了每一天中"苹果" 和 "桔子"的销售情况.

写一个 SQL查询,报告每一天苹果和桔子销售的数目的差异.
返回的结果表,按照格式为('YYYY-MM-DD') 的 sale_date 排序.

查询结果表如下例所示:
Sales 表:
+------------+------------+-------------+
| sale_date  | fruit      | sold_num    |
+------------+------------+-------------+
| 2020-05-01 | apples     | 10          |
| 2020-05-01 | oranges    | 8           |
| 2020-05-02 | apples     | 15          |
| 2020-05-02 | oranges    | 15          |
| 2020-05-03 | apples     | 20          |
| 2020-05-03 | oranges    | 0           |
| 2020-05-04 | apples     | 15          |
| 2020-05-04 | oranges    | 16          |
+------------+------------+-------------+
Result 表:
+------------+--------------+
| sale_date  | diff         |
+------------+--------------+
| 2020-05-01 | 2            |
| 2020-05-02 | 0            |
| 2020-05-03 | 20           |
| 2020-05-04 | -1           |
+------------+--------------+
在 2020-05-01, 卖了 10 个苹果 和 8 个桔子 (差异为 10 - 8 = 2).
在 2020-05-02, 卖了 15 个苹果 和 15 个桔子 (差异为 15 - 15 = 0).
在 2020-05-03, 卖了 20 个苹果 和 0 个桔子 (差异为 20 - 0 = 20).
在 2020-05-04, 卖了 15 个苹果 和 16 个桔子 (差异为 15 - 16 = -1).

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/apples-oranges
//测试数据
Create table If Not Exists Sales (sale_date date, fruit ENUM('apples', 'oranges'), sold_num int);

insert into Sales (sale_date, fruit, sold_num) values ('2020-05-01', 'apples', '10');
insert into Sales (sale_date, fruit, sold_num) values ('2020-05-01', 'oranges', '8');
insert into Sales (sale_date, fruit, sold_num) values ('2020-05-02', 'apples', '15');
insert into Sales (sale_date, fruit, sold_num) values ('2020-05-02', 'oranges', '15');
insert into Sales (sale_date, fruit, sold_num) values ('2020-05-03', 'apples', '20');
insert into Sales (sale_date, fruit, sold_num) values ('2020-05-03', 'oranges', '0');
insert into Sales (sale_date, fruit, sold_num) values ('2020-05-04', 'apples', '15');
insert into Sales (sale_date, fruit, sold_num) values ('2020-05-04', 'oranges', '16');

解题思路

Sales表保存了每天每种水果的销售数量。
题目要求:计算每天苹果与桔子的销量之差。
直观的理解,可以先分别取出每天苹果的销量和桔子的销量,然后相互关联,再计算差值。
但因为苹果或桔子并不一定每天都有销量,因此,不能使用LEFT JOIN或INNER JOIN进行关联,而应该使用FULL JOIN进行关联。


#以下代码使用Oracle模式执行,MySQL不支持FULL JOIN
select
    to_char(coalesce(a.sale_date,b.sale_date),'yyyy-mm-dd') sale_date,
    coalesce(a.sold_num,0)-coalesce(b.sold_num,0) diff
from
(
    select 
        sale_date,
        sold_num
    from Sales
    where fruit = 'apples'
)a
full join
(
    select 
        sale_date,
        sold_num
    from Sales
    where fruit = 'oranges'
)b
on a.sale_date = b.sale_date;

当然,我们也可以使用行转列的方法,将苹果的销量与桔子的销量转化到同一行,从而可以简单的实现差值。
行转列操作,常用的方法为使用GROUP BY+SUM或MAX实现。

参考SQL

未特别说明的情况下,参考SQL为基于MySQL8.0实现。
select
    sale_date,
    apples_sold_num - oranges_sold_num diff
from (
    select
        date_format(sale_date,'%Y-%m-%d') sale_date,
        sum(case when fruit = 'apples' then sold_num else 0 end) apples_sold_num,
        sum(case when fruit = 'oranges' then sold_num else 0 end) oranges_sold_num
    from Sales
    group by sale_date
)a
order by sale_date;

picture loss