这段时间,刷了LeetCode的数据库题目,挺有感触的。在刷这些题之前,我只写过一般的增删改查,尤其是查询操作,使用的也不是很灵活,只知道最基本的用法。
去刷了题目之后真的学到了很多不论是新的知识点还是一些组合用法,总之对数据库操作尤其是dql的使用更加熟练了。感谢其他leetcoder对各种知识点和解题套路的分享,学会这些小操作后,写sql头不疼了,腰不酸了,睡得着了,吃饭也更香了。
根据这些题,我总结了一些常用的知识点、小技巧以及部分有代表性的题解。
这篇文章就来分享一些有价值的题解。题目有些多,这篇先展示其中七题的题解。
剩下的在这里
题目链接
这个题目如果保证员工最多的项目仅有一个或者只需要输出其中的一个就会变得非常简单。
但是问题就在于这个查询结果存在多解,即会有多个项目的员工数量并列第一。
所以我们先要查询出员工最多的项目有多少员工,接着,我们需要从所有的项目里在查询出所有的员工数量大于等于这个数字的项目。
tips:需要使用到all关键字
select
project_id
from
project
group by
project_id
having
count(*) >= all(
select
count(*)
from
project
group by
project_id
)
;
题目链接
同上一题相似,这个题也需要我们找出统计数字最高的元素,并且,存在并列的情况:
所以我们还是采用上一题的策略,先查询出最高元素的数值,再从所用元素中筛选出数值等于它的元素。
SELECT
seller_id
FROM
Sales s
GROUP BY seller_id
HAVING SUM(price) >= all(
SELECT
SUM(price)
FROM
Sales
GROUP BY seller_id
ORDER BY SUM(price) DESC
)
;
题目链接
这里需要我们查找购买了其中一个商品却没有购买另一个商品的用户。
其实就在寻找两个集合交集中的元素。
我们使用in
条件匹配子查询出来的购买了s8和购买了iPhone 1的集合,使用and
运算对集合元素进行交集运算。
select
distinct buyer_id
FROM
Sales
where
buyer_id
in(
SELECT
distinct buyer_id
FROM
Sales s
JOIN Product p
ON p.product_id = s.Product_id
where
product_name = 'S8'
)
and
buyer_id not in(
SELECT
distinct buyer_id
FROM
Sales s
JOIN Product p
ON p.product_id = s.Product_id
where
product_name = 'iphone')
;
题目链接
这个题目需要我们统计仅在一段时间内出售过的产品,不太好搞。
老规矩,正难则反,我们查询所有不再这一时间段内出售过的产品,取这个集合的补集即可
select
distinct p.product_id,
p.product_name
from
Sales s
join product p on s.product_id = p.product_id
where
p.product_id not in(
select
distinct product_id
from
Sales
where
sale_date < '2019-01-01'
or
sale_date > '2019-03-31'
)
;
题目链接
这道题需要我们统计下单日期和送货日期相同的订单占总订单的比例
如果仅是统计即时订单的话,这个题使用一个where语句进行筛选即可,但是那样会筛选掉所有的语句
因此我们需要保留所有的数据,最好不要使用where语句进行筛选,而是在遍历所有数据的时候使用case-when-then来进行筛选。搭配上聚合函数一起使用,我们可以直接得到即时订单的数量和全体的数量,进而得出比率。
select
round(sum(case when order_date = customer_pref_delivery_date then 1 else 0 end)/count(delivery_id)*100,2) as immediate_percentage
from
delivery
;
题目链接
这道题的表单中,存在关联关系,我们的任务是统计所有帖子的评论数,那么就免不了要进行联结。
在联结之前,我们应该先将所有的帖子分离出来放入一张表中。在使用这张表同原表进行联结,进而统计所有帖子的评论数。
另外,题目中提到,帖子和评论都存在重复。对于去重工作,对帖子的去重我们可以在分离帖子的子查询中解决,重复的评论我们可以在分完组后在聚合函数中进行去重。
select
s1.sub_id as post_id,
ifnull(count(distinct s2.sub_id),0) as number_of_comments
from
(
select
distinct sub_id
from
submissions
where
parent_id is null
) s1
left join submissions s2 on s1.sub_id = s2.parent_id
group by
s1.sub_id
;
这道题需要我们统计每件产品销售的平均售价,对于平均售价的计算并不是难事,我们使用聚合函数对单价和数量乘积进行求和即可。
这道题亮点就在于其两个表的联结条件。除了id要对应上除外,我们还需要使得出售时间点位于价格时间段内,因此在联结两张表时我们需要多个条件进行限制,条件之间使用and算符即可。
select
u.product_id,
round(sum(price * units) / sum(units),2) as average_price
from
unitssold u
left join prices p on u.product_id = p.product_id and purchase_date between start_date and end_date
group by
product_id
;