来源:高频 SQL 50 题(基础版)leetcode.cn/studyplan/s…
2356. 每位教师所教授的科目种类的数量
查询每位老师在大学里教授的科目种类的数量。
以 任意顺序 返回结果表。
查询结果格式示例如下。
思路 + SQL 1
这里的难点是通过 teacher_id 分组后,科目很有可能重复,因为了老师会在不同的系里教同一门课。怎么解决呢?加个 distinct 去除组中的重复 subject_id 就完事了。
select
teacher_id,
count(distinct subject_id) as cnt
from
Teacher
group by
teacher_id;
思路 + SQL 2
用另外一种方法,就是在已经去重后的表中进行直接计数,就可以获得结果了。
select
teacher_id,
count(*) as cnt
from
(
select
distinct teacher_id,
subject_id
from
teacher
) as t
group by
teacher_id;
1141. 查询近30天活跃用户数
编写解决方案,统计截至 2019-07-27(包含2019-07-27),近 30 天的每日活跃用户数(当天只要有一条活动记录,即为活跃用户)。
以 任意顺序 返回结果表。
结果示例如下。
思路 + SQL
这题较为简单,只不过考察看题和日期函数的用法。这里统计近 30 天的每日活跃用户,那么就需要将比 2019-07-27 小,但是不能小超过 30 天的所有活动天数找出来。然后得到的表用日期聚类一下,再用 distinct 统计用户数量即可。这里不能用 session_id 来统计用户,因为用户可能有多个 session_id,不用同一个机器访问都会有这问题。
这里需要额外提一下的是,dateDiff 的用法是,DATEDIFF(enddate, startdate),结果是 enddate - startdate 的值,以天数的形式。
select
activity_date as day,
count(distinct user_id) as active_users
from
Activity
where
dateDiff('2019-07-27', activity_date) >= 0
and dateDiff('2019-07-27', activity_date) < 30
group by
activity_date;
1084. 销售分析III
编写解决方案,报告2019年春季才售出的产品。即仅在 2019-01-01 至 2019-03-31(含)之间出售的商品。
以 任意顺序 返回结果表。
结果格式如下所示。
思路 + SQL
这题会理所应当地去连接表之后,然后通过日期范围查询:
select
*
from
Product p
inner join Sales s on p.product_id = s.product_id
where
s.sale_date between '2019-01-01'
and '2019-03-31';
但是这样计算得到的结果是有问题的。因为想要搜索的是仅仅在春季才销售的产品:
有一个比较简单的方法是,通过计数来判断。如果在春季的销售数量等于统计的所有的销售数量,那么就说明仅仅在春季销售了。
- 两表连接,得到商品的销售和详细信息表:
select
*
from
Product p
inner join Sales s on p.product_id = s.product_id;
- 分组后计数。根据
product_id进行分组,对每组进行春季的销售统计和所有的销售统计。如果值相等,说明是仅在春季销售的。
select
p.product_id,
p.product_name
from
Product p
inner join Sales s on p.product_id = s.product_id
group by
p.product_id
having
-- 分组筛选要求:春季销售量 = 所有的销售量
count(
s.sale_date between '2019-01-01'
and '2019-03-31'
or null
) = count(s.sale_date);
这里使用了 or null 的写法,是如果不符合条件就记录为 null,而 null 不会被 count 计数。亲测 or null 比 if 函数还快。
596. 超过5名学生的课
查询 至少有5个学生 的所有班级。
以 任意顺序 返回结果表。
查询结果格式如下所示。
SQL
送分题不解释。
select
class
from
Courses
group by
class
having
count(student) >= 5;
1729. 求关注者的数量
编写解决方案,对于每一个用户,返回该用户的关注者数量。
按 user_id 的顺序返回结果表。
查询结果的格式如下示例所示。
SQL
仍然是一题送分题。
select
user_id,
count(follower_id) as followers_count
from
Followers
group by
user_id
order by
user_id asc;
619. 只出现一次的最大数字
单一数字 是在 MyNumbers 表中只出现一次的数字。
找出最大的 单一数字 。如果不存在 单一数字 ,则返回 null 。
查询结果如下例所示。
思路 + SQL 1
这题很常规地通过分组和 count 方法来计算,理论上可以得到只出现一次的最大值。
select
num
from
MyNumbers
group by
num
having
count(num) = 1
order by
num desc
limit
1;
但是在没有任何符合条件的情况下,返回的是个空表,而不是 null:
空表格代表没有任何的输出,那再根据这个结果再怎么加工都没用。
所以在外层再添加一个 聚类函数 来获取,就可以得到 null 了。下面是一个总结表,可以在空表的查询中返回 null:
select
max(num) as num
from
(
select
num
from
MyNumbers
group by
num
having
count(num) = 1
order by
num desc
limit
1
) t;
思路 + SQL 2
用 select 来接受,如果 select 没有获取到任何值,会返回 null。
select
(
select
num
from
MyNumbers
group by
num
having
count(num) = 1
order by
num desc
limit
1
) as num;
总结
- select 聚类函数等 as param1 from (空表) —> param1:null
- select (空表) as param1 -> param1:null
其他
- limit 语句无法出现新的 null 值
- where 和 having 同样无法出现新的 null 值
1045. 买下所有产品的客户
编写解决方案,报告 Customer 表中购买了 Product 表中所有产品的客户的 id。
返回结果表 无顺序要求 。
返回结果格式如下所示。
思路 + SQL
有了上面的题目的经验,这次也使用 having 条件来过滤分组后的结果。筛选条件为,用户买的种类和 Product 表中的种类数量相等。
select
customer_id
from
Customer
group by
customer_id
having
count(distinct product_key) = (
select
count(product_key)
from
Product
);