题目描述
(通过次数4,032 | 提交次数6,887,通过率58.55%)
Product表: +---------------+---------+ | Column Name | Type | +---------------+---------+ | product_id | int | | product_name | varchar | +---------------+---------+ product_id 是这张表的主键。 product_name 是产品的名称。 Sales表: +---------------------+---------+ | Column Name | Type | +---------------------+---------+ | product_id | int | | period_start | date | | period_end | date | | average_daily_sales | int | +---------------------+---------+ product_id 是这张表的主键。 period_start和 period_end是该产品销售期的起始日期和结束日期,且这两个日期包含在销售期内。 average_daily_sales 列存储销售期内该产品的日平均销售额。 编写一段 SQL 查询每个产品每年的总销售额,并包含 product_id, product_name 以及 report_year 等信息。 销售年份的日期介于 2018 年到 2020 年之间。你返回的结果需要按product_id 和 report_year 排序。 查询结果格式如下例所示。 示例 1: 输入: Product table: +------------+--------------+ | product_id | product_name | +------------+--------------+ | 1 | LC Phone | | 2 | LC T-Shirt | | 3 | LC Keychain | +------------+--------------+ Sales table: +------------+--------------+-------------+---------------------+ | product_id | period_start | period_end | average_daily_sales | +------------+--------------+-------------+---------------------+ | 1 | 2019-01-25 | 2019-02-28 | 100 | | 2 | 2018-12-01 | 2020-01-01 | 10 | | 3 | 2019-12-01 | 2020-01-31 | 1 | +------------+--------------+-------------+---------------------+ 输出: +------------+--------------+-------------+--------------+ | product_id | product_name | report_year | total_amount | +------------+--------------+-------------+--------------+ | 1 | LC Phone | 2019 | 3500 | | 2 | LC T-Shirt | 2018 | 310 | | 2 | LC T-Shirt | 2019 | 3650 | | 2 | LC T-Shirt | 2020 | 10 | | 3 | LC Keychain | 2019 | 31 | | 3 | LC Keychain | 2020 | 31 | +------------+--------------+-------------+--------------+ 解释: LC Phone 在 2019-01-25 至 2019-02-28 期间销售,该产品销售时间总计35天。销售总额 35*100 = 3500。 LC T-shirt 在 2018-12-01至 2020-01-01 期间销售,该产品在2018年、2019年、2020年的销售时间分别是31天、365天、1天,2018年、2019年、2020年的销售总额分别是31*10=310、365*10=3650、1*10=10。 LC Keychain 在 2019-12-01至 2020-01-31 期间销售,该产品在2019年、2020年的销售时间分别是:31天、31天,2019年、2020年的销售总额分别是31*1=31、31*1=31。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/total-sales-amount-by-year
//测试数据 Create table If Not Exists Product (product_id int, product_name varchar(30)); Create table If Not Exists Sales (product_id int, period_start date, period_end date, average_daily_sales int); insert into Product (product_id, product_name) values ('1', 'LC Phone '); insert into Product (product_id, product_name) values ('2', 'LC T-Shirt'); insert into Product (product_id, product_name) values ('3', 'LC Keychain'); insert into Sales (product_id, period_start, period_end, average_daily_sales) values ('1', '2019-01-25', '2019-02-28', '100'); insert into Sales (product_id, period_start, period_end, average_daily_sales) values ('2', '2018-12-01', '2020-01-01', '10'); insert into Sales (product_id, period_start, period_end, average_daily_sales) values ('3', '2019-12-01', '2020-01-31', '1');
解题思路
Sales源表记录了某一个时间区间内的平均销售额。这个时间区间可能是某一年内的,也可能是跨年的。
现题目要求,计算每一年的总销售额。
每一年的总销售额=这一年中每天的销售额的汇总
**每天的销售额按它所属的时间区间内的日平均销售额计算。**
这样,我们只要计算出每一天对应的时间区间,然后使用这个时间区间内的日平均销售额作为这一天的销售额。再按年汇总即可。
因为源表是个时间区间,而我们需要这个时间区间内的每一天。
所以,需要将时间区间按天展开。
在SQL语言中,递归可以很好的完成这样的计算。
with recursive t(product_id,period_date) as ( select product_id,period_start as period_date from Sales union all select product_id,date_add(period_date,interval 1 day) period_date from t where exists(select 1 from Sales s where t.product_id = s.product_id and t.period_date < s.period_end) ) select * from t;
上面的SQL语句中,从product_id、区间起始日出发,按天依次递增,直到区间结束日。这样就完成了区间的展开。
接下来,将日期转化为年,然后与product_id一起,分组汇总统计即可。
参考SQL
未特别说明的情况下,参考SQL为基于MySQL8.0实现。
select round(sum(a.TIV_2016),2) as tiv_2016 from insurance a where exists(select 1 from insurance b where a.TIV_2015 = b.TIV_2015 and a.PID<>b.PID) and not exists(select 1 from insurance c where a.LAT = c.LAT and a.LON = c.LON and a.PID<>c.PID);
本站所有内容均为原创,本站保留所有权利。仅允许非商业用途的转载,但必须注明来源网站、作者、来源链接!否则,由此造成的一切后果,由转载方承担!
干货分享、技术提升、面试笔试、学习交流,欢迎关注公众号:xuesql。QQ学习交流群:209942678。