详解力扣高频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;


