题目描述
(通过次数5,893 | 提交次数8,629,通过率68.29%)
表: Customers +---------------+---------+ | Column Name | Type | +---------------+---------+ | customer_id | int | | name | varchar | +---------------+---------+ customer_id 是该表主键. 该表包含消费者的信息. 表: Orders +---------------+---------+ | Column Name | Type | +---------------+---------+ | order_id | int | | order_date | date | | customer_id | int | | product_id | int | +---------------+---------+ order_id 是该表主键. 该表包含消费者customer_id产生的订单. 不会有商品被相同的用户在一天内下单超过一次. 表: Products +---------------+---------+ | Column Name | Type | +---------------+---------+ | product_id | int | | product_name | varchar | | price | int | +---------------+---------+ product_id 是该表主键. 该表包含所有商品的信息. 写一个SQL 语句, 找到每件商品的最新订单(可能有多个). 返回的结果以 product_name 升序排列, 如果有排序相同, 再以 product_id 升序排列. 如果还有排序相同, 再以 order_id 升序排列. 查询结果格式如下例所示。 示例 1: 输入: Customers表: +-------------+-----------+ | customer_id | name | +-------------+-----------+ | 1 | Winston | | 2 | Jonathan | | 3 | Annabelle | | 4 | Marwan | | 5 | Khaled | +-------------+-----------+ Orders表: +----------+------------+-------------+------------+ | order_id | order_date | customer_id | product_id | +----------+------------+-------------+------------+ | 1 | 2020-07-31 | 1 | 1 | | 2 | 2020-07-30 | 2 | 2 | | 3 | 2020-08-29 | 3 | 3 | | 4 | 2020-07-29 | 4 | 1 | | 5 | 2020-06-10 | 1 | 2 | | 6 | 2020-08-01 | 2 | 1 | | 7 | 2020-08-01 | 3 | 1 | | 8 | 2020-08-03 | 1 | 2 | | 9 | 2020-08-07 | 2 | 3 | | 10 | 2020-07-15 | 1 | 2 | +----------+------------+-------------+------------+ Products表: +------------+--------------+-------+ | product_id | product_name | price | +------------+--------------+-------+ | 1 | keyboard | 120 | | 2 | mouse | 80 | | 3 | screen | 600 | | 4 | hard disk | 450 | +------------+--------------+-------+ 输出: +--------------+------------+----------+------------+ | product_name | product_id | order_id | order_date | +--------------+------------+----------+------------+ | keyboard | 1 | 6 | 2020-08-01 | | keyboard | 1 | 7 | 2020-08-01 | | mouse | 2 | 8 | 2020-08-03 | | screen | 3 | 3 | 2020-08-29 | +--------------+------------+----------+------------+ 解释: keyboard 的最新订单在2020-08-01, 在这天有两次下单. mouse 的最新订单在2020-08-03, 在这天只有一次下单. screen 的最新订单在2020-08-29, 在这天只有一次下单. hard disk 没有被下单, 我们不把它包含在结果表中. 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/the-most-recent-orders-for-each-product
//测试数据 Create table If Not Exists Customers (customer_id int, name varchar(10)); Create table If Not Exists Orders (order_id int, order_date date, customer_id int, product_id int); Create table If Not Exists Products (product_id int, product_name varchar(20), price int); insert into Customers (customer_id, name) values ('1', 'Winston'); insert into Customers (customer_id, name) values ('2', 'Jonathan'); insert into Customers (customer_id, name) values ('3', 'Annabelle'); insert into Customers (customer_id, name) values ('4', 'Marwan'); insert into Customers (customer_id, name) values ('5', 'Khaled'); insert into Orders (order_id, order_date, customer_id, product_id) values ('1', '2020-07-31', '1', '1'); insert into Orders (order_id, order_date, customer_id, product_id) values ('2', '2020-7-30', '2', '2'); insert into Orders (order_id, order_date, customer_id, product_id) values ('3', '2020-08-29', '3', '3'); insert into Orders (order_id, order_date, customer_id, product_id) values ('4', '2020-07-29', '4', '1'); insert into Orders (order_id, order_date, customer_id, product_id) values ('5', '2020-06-10', '1', '2'); insert into Orders (order_id, order_date, customer_id, product_id) values ('6', '2020-08-01', '2', '1'); insert into Orders (order_id, order_date, customer_id, product_id) values ('7', '2020-08-01', '3', '1'); insert into Orders (order_id, order_date, customer_id, product_id) values ('8', '2020-08-03', '1', '2'); insert into Orders (order_id, order_date, customer_id, product_id) values ('9', '2020-08-07', '2', '3'); insert into Orders (order_id, order_date, customer_id, product_id) values ('10', '2020-07-15', '1', '2'); insert into Products (product_id, product_name, price) values ('1', 'keyboard', '120'); insert into Products (product_id, product_name, price) values ('2', 'mouse', '80'); insert into Products (product_id, product_name, price) values ('3', 'screen', '600'); insert into Products (product_id, product_name, price) values ('4', 'hard disk', '450');
解题思路
跟1077. 项目员工 III一样,这道题考查的也是分组内排名,然后返回前N名的写法。
但是也有2点特殊要求:
第一,如果最新的一天有多条记录,那么都需要返回;
第二,对于返回的结果,需要按要求排序:返回的结果以 product_name 升序排列, 如果有排序相同, 再以 product_id 升序排列. 如果还有排序相同, 再以 order_id 升序排列;
那么,在实现上,也主要是分为以下3个步骤:
第一步,先计算出每个产品每个订单日期的排名(倒序),如果最新的日期内有多笔订单,则需要全部返回。
针对这类分组内排序后取前N名的需求,有三个分析函数可以使用,分别是:row_number、rank、dense_rank。
根据需求,这里比较适合使用的是rank和dense_rank,然后限定排序序号为1即可。
第二步,关联出返回结果中需要的product_name。可以使用product_id与Products关联,获取product_name的值。
第三步,使用order by子句,对返回的结果集进行排序。
参考SQL
未特别说明的情况下,参考SQL为基于MySQL8.0实现。
select c.product_name, b.product_id, b.order_id, b.order_date from ( select a.product_id, a.order_id, a.order_date, rank() over(partition by a.product_id order by order_date desc) rk from Orders a )b left join Products c on b.product_id = c.product_id where b.rk = 1 order by c.product_name,b.product_id,b.order_id;
本站所有内容均为原创,本站保留所有权利。仅允许非商业用途的转载,但必须注明来源网站、作者、来源链接!否则,由此造成的一切后果,由转载方承担!
干货分享、技术提升、面试笔试、学习交流,欢迎关注公众号:xuesql。QQ学习交流群:209942678。