思路
在SQL的刷题类型中,很多时候会出现筛选类的题目,这类题目如果以直接思维来思考,会牵扯到去重,排序以及一些较为复杂的逻辑,但是将其转化为一种数字化的问题,则可以较为容易的解决
(注:以下题目类型以及部分解答思路均转自力扣(LeetCode),有需要可自行在力扣网上查找)
买下所有产品的客户
返回顾客的ID
根据题目要求,应该会返回customer_id为1和3的用户,这里的关键思路为:
顾客去重后购买的商品数应该与产品数是一致的
1.按顾客分类
2.算出顾客去重的购买数
3.比较商品总数
select
customer_id
from Customer
group by customer_id
having count(distinct product_key) = (select count(product_key) from Product)
#distinct 去重 count则可以代表总类
销售分析Ⅱ
结果返回购买者的ID
该题思路与上题思路类似,从第一感觉来讲,可以运用到where in 的方法进行筛选,但这种方法较为复杂。可以思考,将‘购买和未购买’进行一个数字化的表现
select buyer_id
from Sales left outer join Product on Sales.product_id = Product.product_id
group by buyer_id
having sum(product_name='S8')>0 and sum(product_name='iPhone')=0
#sum()其中的表达式为真 则返回1,否则返回0.
这里同样可以使用 case when / count if 这样的函数和函数组合来达到想要的目的
消费者的下单频率
结果返回客户ID和姓名
该题是数字化思想最为突出的一道题。如果不将筛选条件进行数字化,在力扣的解题讨论中,就会出现大量的多次join 和 子查询的情况,虽然思考逻辑很简单,但是代码实现的过程就会显得很复杂繁冗易出错。我们根据上题中,对月份条件进行数字化,就可以得到较为简单的代码:
select
Orders.customer_id,
Customers.name
from Orders
left join Customers on Customers.customer_id = Orders.customer_id
left join Product on Product.product_id = Orders.product_id
group by Orders.customer_id
having (sum(quantity*price*(left(order_date,7)='2020-06'))>=100 and sum(quantity*price*(left(order_date,7)='2020-07'))>=100 )
left函数和日期构建出对应的时间作为字符串来进行数字化判断,如果为真输出1,不影响乘法的运算;如果为假,输出为0,也作为了筛选的条件
总结
筛选条件的数字化,很多时候可以解决多次 where in 或者join的情况,从而简化代码