详解力扣高频SQL50题之1581. 进店却未进行过交易的顾客【中等】
传送门:1581. 进店却未进行过交易的顾客
题目
表:Visits
±------------±--------+
| Column Name | Type |
±------------±--------+
| visit_id | int |
| customer_id | int |
±------------±--------+
visit_id 是该表中具有唯一值的列。
该表包含有关光临过购物中心的顾客的信息。
表:Transactions
±---------------±--------+
| Column Name | Type |
±---------------±--------+
| transaction_id | int |
| visit_id | int |
| amount | int |
±---------------±--------+
transaction_id 是该表中具有唯一值的列。
此表包含 visit_id 期间进行的交易的信息。
有一些顾客可能光顾了购物中心但没有进行交易。请你编写一个解决方案,来查找这些顾客的 ID ,以及他们只光顾不交易的次数。
返回以 任何顺序 排序的结果表。
返回结果格式如下例所示。
示例 1:
输入:
Visits
±---------±------------+
| visit_id | customer_id |
±---------±------------+
| 1 | 23 |
| 2 | 9 |
| 4 | 30 |
| 5 | 54 |
| 6 | 96 |
| 7 | 54 |
| 8 | 54 |
±---------±------------+
Transactions
±---------------±---------±-------+
| transaction_id | visit_id | amount |
±---------------±---------±-------+
| 2 | 5 | 310 |
| 3 | 5 | 300 |
| 9 | 5 | 200 |
| 12 | 1 | 910 |
| 13 | 2 | 970 |
±---------------±---------±-------+
输出:
±------------±---------------+
| customer_id | count_no_trans |
±------------±---------------+
| 54 | 2 |
| 30 | 1 |
| 96 | 1 |
±------------±---------------+
解析
原题是有示例解释的,但解释就是一坨,可读性极差,所以本人删除了。这题对分析表格能力要求较高,难度百分百有中等级别,而不是官方标注的简单,误人子弟。
首先看第一个输出记录,意思是客户54只顾光顾不交易2次,具体来说,是54在访问表中出现3次,对应的访问id是5,7,8,而只有5在交易表中出现了,所以只交易一次,也就是不交易两次,因为7和8都没有对应的交易记录。如果这点看不出来,可以尝试左连接访问表和交易表,然后运行,查看连接后的表格,对应的代码和效果如下:
select *from Visits vleft join Transactions ton v.visit_id=t.visit_id;
显然,7和8对应的交易记录(蓝色部分)都为null,只有5存在交易记录(绿色部分)。理解了这点,也就抓住了题目的突破口,即按客户id分组,统计交易id为null的个数,即访问但未交易的次数,不为null则说明访问了也交易了,无需统计。至此,核心算法结束,当然统计其他为null的字段也是可以的,只是统计交易id更容易理解。
整理下,先左连接访问表和交易表,再筛选交易id为null的记录,再按客户id分组,组内个数即访问但未交易的次数。
代码(标准SQL)
select customer_id,count(*) as count_no_trans from Visits vleft join Transactions ton v.visit_id=t.visit_idwhere t.visit_id is nullgroup by customer_id;