题目描述
(通过次数1,664 | 提交次数2,011,通过率82.74%)
活动表: Orders +-------------+------+ | Column Name | Type | +-------------+------+ | order_id | int | | customer_id | int | | order_type | int | +-------------+------+ order_id是此表的主键列。 此表的每一行都表示订单的ID、订购该订单的客户的ID以及订单类型。 订单可以是类型0或类型1。 编写SQL查询以根据以下条件报告所有订单: 如果客户至少有一个类型为0的订单,则不要报告该客户的任何类型为1的订单。 否则,报告客户的所有订单。 按任意顺序返回结果表。 查询结果格式如下例所示。 示例 1: 输入: Orders table: +----------+-------------+------------+ | order_id | customer_id | order_type | +----------+-------------+------------+ | 1 | 1 | 0 | | 2 | 1 | 0 | | 11 | 2 | 0 | | 12 | 2 | 1 | | 21 | 3 | 1 | | 22 | 3 | 0 | | 31 | 4 | 1 | | 32 | 4 | 1 | +----------+-------------+------------+ 输出: +----------+-------------+------------+ | order_id | customer_id | order_type | +----------+-------------+------------+ | 31 | 4 | 1 | | 32 | 4 | 1 | | 1 | 1 | 0 | | 2 | 1 | 0 | | 11 | 2 | 0 | | 22 | 3 | 0 | +----------+-------------+------------+ 解释: 客户1有两个类型为0的订单。我们两个都返回。 客户2的订单类型为0,订单类型为1。我们只返回类型为0的订单。 客户3的订单类型为0,订单类型为1。我们只返回类型为0的订单。 客户4有两个类型1的订单。我们两个都返回。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/drop-type-1-orders-for-customers-with-type-0-orders
//测试数据 Create table If Not Exists Orders (order_id int, customer_id int, order_type int); insert into Orders (order_id, customer_id, order_type) values ('1', '1', '0'); insert into Orders (order_id, customer_id, order_type) values ('2', '1', '0'); insert into Orders (order_id, customer_id, order_type) values ('11', '2', '0'); insert into Orders (order_id, customer_id, order_type) values ('12', '2', '1'); insert into Orders (order_id, customer_id, order_type) values ('21', '3', '1'); insert into Orders (order_id, customer_id, order_type) values ('22', '3', '0'); insert into Orders (order_id, customer_id, order_type) values ('31', '4', '1'); insert into Orders (order_id, customer_id, order_type) values ('32', '4', '1');
解题思路
Orders表中保存了类型为0和1的所有订单。
题目要求:如果某客户存在类型为0、1的订单,那么仅返回该客户类型为0的订单;
如果某客户仅存在类型为0的订单,那么返回该客户类型为0的订单;
如果某客户仅存在类型为1的订单,那么返回该客户类型为1的订单;
从直观上理解,可以对类型为0和类型为1的订单分别查询。
类型为0的所有订单都需要返回。
类型为1的订单,只有当客户不存在类型为0的订单时才返回。
然后将这两部分结果合并即可。
select a.order_id, a.customer_id, a.order_type from Orders a where a.order_type = 0 union all select a.order_id, a.customer_id, a.order_type from Orders a where a.order_type = 1 and not exists(select 1 from Orders b where a.customer_id = b.customer_id and b.order_type = 0);
除了上面的思路外,也可以从另一个方向思考:
当某客户存在类型为0、1的订单时,只返回类型为0的订单;
当某客户仅存在类型为0的订单时,需要返回;
当某客户仅存在类型为1的订单时,也需要返回;
那么,其实,这也是一个开窗排序的场景,按类型从小到大排序,只取序号为1的订单。
下面的参考SQL即是按这个思路实现的。
参考SQL
未特别说明的情况下,参考SQL为基于MySQL8.0实现。
select b.order_id, b.customer_id, b.order_type from ( select a.order_id, a.customer_id, a.order_type, rank() over(partition by a.customer_id order by a.order_type) rk from Orders a ) b where b.rk = 1;
本站所有内容均为原创,本站保留所有权利。仅允许非商业用途的转载,但必须注明来源网站、作者、来源链接!否则,由此造成的一切后果,由转载方承担!
干货分享、技术提升、面试笔试、学习交流,欢迎关注公众号:xuesql。QQ学习交流群:209942678。