1. 力扣1990:统计实验的数量
1.1 题目:
表: Experiments
+-----------------+------+
| Column Name | Type |
+-----------------+------+
| experiment_id | int |
| platform | enum |
| experiment_name | enum |
+-----------------+------+
experiment_id 是这个表的主键.
platform 是枚举类型的,取值是这三种 ('Android', 'IOS', 'Web') 之一.
experiment_name 也是枚举类型的,取值是这三种 ('Reading', 'Sports', 'Programming') 之一.
这个表包含有关随机实验人员进行的实验的 ID、用于做实验的平台以及实验名称的信息。
写一个 SQL 查询语句,以报告在给定三个实验平台中每种实验完成的次数。请注意,每一对(实验平台、实验名称)都应包含在输出中,包括平台上实验次数是零的。
结果可以以任意顺序给出。
查询的结果如下所示:
示例:
输入:
Experiments table:
+---------------+----------+-----------------+
| experiment_id | platform | experiment_name |
+---------------+----------+-----------------+
| 4 | IOS | Programming |
| 13 | IOS | Sports |
| 14 | Android | Reading |
| 8 | Web | Reading |
| 12 | Web | Reading |
| 18 | Web | Programming |
+---------------+----------+-----------------+
输出:
+----------+-----------------+-----------------+
| platform | experiment_name | num_experiments |
+----------+-----------------+-----------------+
| Android | Reading | 1 |
| Android | Sports | 0 |
| Android | Programming | 0 |
| IOS | Reading | 0 |
| IOS | Sports | 1 |
| IOS | Programming | 1 |
| Web | Reading | 2 |
| Web | Sports | 0 |
| Web | Programming | 1 |
+----------+-----------------+-----------------+
解释:
在安卓平台上, 我们只做了一个"Reading" 实验.
在 "IOS" 平台上,我们做了一个"Sports" 实验和一个"Programming" 实验.
在 "Web" 平台上,我们做了两个"Reading" 实验和一个"Programming" 实验.
1.2 思路:
看注释。
1.3 题解:
sql
-- 先创建一张关于三个实验平台每种实验的表
with tep1 as (
select 'Android' platform
union all
select 'IOS' platform
union all
select 'Web' platform
), tep2 as (
select 'Reading' experiment_name
union all
select 'Sports' experiment_name
union all
select 'Programming' experiment_name
), tep3 as (
select *
from tep1, tep2
)
-- 然后与Experiments左外连接,experiment_id为null=>平台上实验次数为0
select t1.platform, t1.experiment_name, if(experiment_id is null, 0, count(*)) num_experiments
from tep3 t1
left join Experiments t2
on t1.platform = t2.platform
and t1.experiment_name = t2.experiment_name
group by t1.platform, t1.experiment_name
2. 力扣2020:无流量的账户数
2.1 题目:
表: Subscriptions
+-------------+------+
| Column Name | Type |
+-------------+------+
| account_id | int |
| start_date | date |
| end_date | date |
+-------------+------+
account_id 是此表的主键列。
此表的每一行都表示帐户订阅的开始和结束日期。
请注意,始终开始日期 < 结束日期。
表: Streams
+-------------+------+
| Column Name | Type |
+-------------+------+
| session_id | int |
| account_id | int |
| stream_date | date |
+-------------+------+
session_id是该表的主键列。
account_id是订阅表中的外键。
此表的每一行都包含与会话相关联的帐户和日期的信息。
编写SQL查询以报告在 2021
购买订阅但没有任何会话的帐 户数。
查询结果格式如下例所示。
示例1:
输入:
Subscriptions table:
+------------+------------+------------+
| account_id | start_date | end_date |
+------------+------------+------------+
| 9 | 2020-02-18 | 2021-10-30 |
| 3 | 2021-09-21 | 2021-11-13 |
| 11 | 2020-02-28 | 2020-08-18 |
| 13 | 2021-04-20 | 2021-09-22 |
| 4 | 2020-10-26 | 2021-05-08 |
| 5 | 2020-09-11 | 2021-01-17 |
+------------+------------+------------+
Streams table:
+------------+------------+-------------+
| session_id | account_id | stream_date |
+------------+------------+-------------+
| 14 | 9 | 2020-05-16 |
| 16 | 3 | 2021-10-27 |
| 18 | 11 | 2020-04-29 |
| 17 | 13 | 2021-08-08 |
| 19 | 4 | 2020-12-31 |
| 13 | 5 | 2021-01-05 |
+------------+------------+-------------+
输出:
+----------------+
| accounts_count |
+----------------+
| 2 |
+----------------+
解释:用户 4 和 9 在 2021 没有会话。
用户 11 在 2021 没有订阅。
2.2 思路:
2.3 题解:
sql
with tep1 as (
-- 查询那些人购买了订阅
select account_id
from Subscriptions
where substring(start_date, 1, 4) = '2021' or substring(end_date, 1, 4) = '2021'
), tep2 as (
-- 之所以这里我使用了distinct先去重,我觉得账户可能由多个会话,而且都不在2021年这种情况。
select distinct account_id
from Streams
where substring(stream_date , 1, 4) <> '2021'
and account_id in (
select * from tep1
)
)
select count(*) accounts_count from tep2
3. 力扣2051:商店中每个成员的级别
3.1 题目:
表: Members
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| member_id | int |
| name | varchar |
+-------------+---------+
member_id 是该表的主键。
该表的每一行都表示成员的名称和 ID。
表: Visits
+-------------+------+
| Column Name | Type |
+-------------+------+
| visit_id | int |
| member_id | int |
| visit_date | date |
+-------------+------+
visit_id 是该表的主键。
member_id 是 Members 表中 member_id 的外键。
该表的每一行都包含关于访问商店的日期和访问该商店的成员的信息。
表: Purchases
+----------------+------+
| Column Name | Type |
+----------------+------+
| visit_id | int |
| charged_amount | int |
+----------------+------+
visit_id 是该表的主键。
visit_id 是访问表 visit_id 的外键。
该表的每一行都包含了关于在商店中消费的信息。
一个商店想对其成员进行分类。有三个层次:
- "钻石" : 如果转换率 大于或等于
80
. - "黄金" : 如果转换率 大于或等于
50
且小于80
. - "白银" : 如果转化率 小于
50
. - "青铜": 如果该成员从未访问过该商店。
成员的 转化率 为 (100 * 该会员的购买总数) / 该成员的总访问次数
.
编写一个 SQL 来查询每个成员的 id、名称和类别。
以 任意顺序返回结果表。
查询结果格式如下所示。
示例 1:
输入:
Members 表:
+-----------+---------+
| member_id | name |
+-----------+---------+
| 9 | Alice |
| 11 | Bob |
| 3 | Winston |
| 8 | Hercy |
| 1 | Narihan |
+-----------+---------+
Visits 表:
+----------+-----------+------------+
| visit_id | member_id | visit_date |
+----------+-----------+------------+
| 22 | 11 | 2021-10-28 |
| 16 | 11 | 2021-01-12 |
| 18 | 9 | 2021-12-10 |
| 19 | 3 | 2021-10-19 |
| 12 | 11 | 2021-03-01 |
| 17 | 8 | 2021-05-07 |
| 21 | 9 | 2021-05-12 |
+----------+-----------+------------+
Purchases 表:
+----------+----------------+
| visit_id | charged_amount |
+----------+----------------+
| 12 | 2000 |
| 18 | 9000 |
| 17 | 7000 |
+----------+----------------+
输出:
+-----------+---------+----------+
| member_id | name | category |
+-----------+---------+----------+
| 1 | Narihan | Bronze |
| 3 | Winston | Silver |
| 8 | Hercy | Diamond |
| 9 | Alice | Gold |
| 11 | Bob | Silver |
+-----------+---------+----------+
解释:
- id = 1 的成员 Narihan 没有访问过该商店。她获得了铜奖。
- id = 3 的成员 Winston 访问了商店一次,但没有购买任何东西。转化率=(100 * 0)/ 1 = 0。他获得了银奖。
- id = 8 的成员 Hercy 访问商店一次,购买一次。转化率=(100 * 1)/ 1 = 1。他获得了钻石奖。
- id = 9 的成员 Alice 访问了商店两次,购买了一次。转化率=(100 * 1)/ 2 = 50。她获得了金奖。
- id = 11 的用户 Bob 访问了商店三次,购买了一次。转化率=(100 * 1)/ 3 = 33.33。他获得了银奖。
3.2 思路:
写的好长,隔着一天没看懒的看这么长的sql 了。
3.3 题解:
sql
with tep1 as (
select member_id , t1.visit_id , charged_amount
from Visits t1
left join Purchases t2
on t1.visit_id = t2.visit_id
), tep2 as (
select member_id,
(select count(charged_amount) from tep1 t2 where t1.member_id = t2.member_id)
/ (select count(*) from tep1 t2 where t1.member_id = t2.member_id) * 100 perc
from tep1 t1
group by member_id
), tep3 as (
select member_id,
case when perc >= 80 then 'Diamond'
when perc >= 50 then 'Gold'
else 'Silver'
end category
from tep2
)
select t1.member_id, name, category
from tep3 t1
join Members t2
on t1.member_id = t2.member_id
union all
select member_id, name, 'Bronze' category
from Members
where member_id not in (
select member_id from tep1
)