LeetcodeSQL<1821-1926>HQL

91 阅读10分钟

1821_Easy_发票中的产品金额

Product 表:

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| product_id  | int     |
| name        | varchar |
+-------------+---------+
product_id 是这张表的主键
表中含有产品 id 、产品名称。产品名称都是小写的英文字母,产品名称都是唯一的

Invoice 表:

+-------------+------+
| Column Name | Type |
+-------------+------+
| invoice_id  | int  |
| product_id  | int  |
| rest        | int  |
| paid        | int  |
| canceled    | int  |
| refunded    | int  |
+-------------+------+
invoice_id 发票 id ,是这张表的主键
product_id 产品 id
rest 应缴款项
paid 已支付金额
canceled 已取消金额
refunded 已退款金额

要求写一个SQL查询,返回全部发票中每个产品的产品名称、总应缴款项、总已支付金额、总已取消金额、总已退款金额

查询结果按 product_name排序

示例:

Product 表:
+------------+-------+
| product_id | name  |
+------------+-------+
| 0          | ham   |
| 1          | bacon |
+------------+-------+
Invoice table:
+------------+------------+------+------+----------+----------+
| invoice_id | product_id | rest | paid | canceled | refunded |
+------------+------------+------+------+----------+----------+
| 23         | 0          | 2    | 0    | 5        | 0        |
| 12         | 0          | 0    | 4    | 0        | 3        |
| 1          | 1          | 1    | 1    | 0        | 1        |
| 2          | 1          | 1    | 0    | 1        | 1        |
| 3          | 1          | 0    | 1    | 1        | 1        |
| 4          | 1          | 1    | 1    | 1        | 0        |
+------------+------------+------+------+----------+----------+
Result 表:
+-------+------+------+----------+----------+
| name  | rest | paid | canceled | refunded |
+-------+------+------+----------+----------+
| bacon | 3    | 3    | 3        | 3        |
| ham   | 2    | 4    | 5        | 3        |
+-------+------+------+----------+----------+
- bacon 的总应缴款项为 1 + 1 + 0 + 1 = 3
- bacon 的总已支付金额为 1 + 0 + 1 + 1 = 3
- bacon 的总已取消金额为 0 + 1 + 1 + 1 = 3
- bacon 的总已退款金额为 1 + 1 + 1 + 0 = 3
- ham 的总应缴款项为 2 + 0 = 2
- ham 的总已支付金额为 0 + 4 = 4
- ham 的总已取消金额为 5 + 0 = 5
- ham 的总已退款金额为 0 + 3 = 3

建表+导数

create table 1821_Product(product_id int, name string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
load data inpath "/leetcode/1812_Product" overwrite into table 1821_Product;
select * from 1821_Product

create table 1821_Invoice(invoice_id int, product_id int, rest int, paid int, canceled int, refunded int) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
load data inpath "/leetcode/1812_Invoice" overwrite into table 1821_Invoice;
select * from 1821_Invoice

知识点:

select 
p.name, sum(i.rest) rest, sum(i.paid) paid, sum(i.canceled) canceled, sum(i.refunded) refunded
from 1821_Product p
left join 1821_Invoice i
on p.product_id=i.product_id
group by p.name

执行结果; image.png

1827_Easy_无效的推文

表:Tweets

+----------------+---------+
| Column Name    | Type    |
+----------------+---------+
| tweet_id       | int     |
| content        | varchar |
+----------------+---------+
tweet_id 是这个表的主键。
这个表包含某社交媒体 App 中所有的推文。

写一条SQL 语句,查询所有无效推文的编号(ID)。当推文内容中的字符数严格大于 15 时,该推文是无效的。

任意顺序返回结果表。

查询结果格式如下示例所示:

Tweets 表:
+----------+----------------------------------+
| tweet_id | content                          |
+----------+----------------------------------+
| 1        | Vote for Biden                   |
| 2        | Let us make America great again! |
+----------+----------------------------------+

结果表:
+----------+
| tweet_id |
+----------+
| 2        |
+----------+
推文 1 的长度 length = 14。该推文是有效的。
推文 2 的长度 length = 32。该推文是无效的。

建表+导数

create table 1827_Tweets(tweet_id int, content string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
load data inpath "/leetcode/1827_Tweets" overwrite into table 1827_Tweets;
select * from 1827_Tweets

知识点:length

select 
tweet_id
from 1827_Tweets 
where length(content) > 15

image.png

1837_Easy_每天的领导和合伙人

表:DailySales

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| date_id     | date    |
| make_name   | varchar |
| lead_id     | int     |
| partner_id  | int     |
+-------------+---------+
该表没有主键。
该表包含日期、产品的名称,以及售给的领导和合伙人的编号。
名称只包含小写英文字母。

写一条 SQL 语句,使得对于每一个date_idmake_name,返回不同lead_id以及不同partner_id的数量。

按任意顺序返回结果表。

查询结果格式如下示例所示:

DailySales 表:
+-----------+-----------+---------+------------+
| date_id   | make_name | lead_id | partner_id |
+-----------+-----------+---------+------------+
| 2020-12-8 | toyota    | 0       | 1          |
| 2020-12-8 | toyota    | 1       | 0          |
| 2020-12-8 | toyota    | 1       | 2          |
| 2020-12-7 | toyota    | 0       | 2          |
| 2020-12-7 | toyota    | 0       | 1          |
| 2020-12-8 | honda     | 1       | 2          |
| 2020-12-8 | honda     | 2       | 1          |
| 2020-12-7 | honda     | 0       | 1          |
| 2020-12-7 | honda     | 1       | 2          |
| 2020-12-7 | honda     | 2       | 1          |
+-----------+-----------+---------+------------+
结果表:
+-----------+-----------+--------------+-----------------+
| date_id   | make_name | unique_leads | unique_partners |
+-----------+-----------+--------------+-----------------+
| 2020-12-8 | toyota    | 2            | 3               |
| 2020-12-7 | toyota    | 1            | 2               |
| 2020-12-8 | honda     | 2            | 2               |
| 2020-12-7 | honda     | 3            | 2               |
+-----------+-----------+--------------+-----------------+
 2020-12-8,丰田(toyota)有领导者 = [0, 1] 和合伙人 = [0, 1, 2] ,同时本田(honda)有领导者 = [1, 2] 和合伙人 = [1, 2]
 2020-12-7,丰田(toyota)有领导者 = [0] 和合伙人 = [1, 2] ,同时本田(honda)有领导者 = [0, 1, 2] 和合伙人 = [1, 2]

建表+导数

drop table 1837_DailySales
create table 1837_DailySales(date_id date, make_name string, lead_id int, partner_id int) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
load data inpath "/leetcode/1837_DailySales" overwrite into table 1837_DailySales;
select * from 1837_DailySales

知识点:count(distinct(xxx))

select 
date_id, make_name, count(distinct(lead_id)) unique_leads , count(distinct(partner_id)) unique_partners 
from 1837_DailySales 
group by date_id, make_name

执行结果: image.png

1842_Medium_两人之间的通话次数

表:Calls

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| from_id     | int     |
| to_id       | int     |
| duration    | int     |
+-------------+---------+
该表没有主键,可能存在重复项。
该表包含 from_id 与 to_id 间的一次电话的时长。
from_id != to_id

编写 SQL 语句,查询每一对用户(person1, person2)之间的通话次数和通话总时长,其中person1 < person2

以任意顺序返回结果表。

查询结果格式如下示例所示:

Calls 表:
+---------+-------+----------+
| from_id | to_id | duration |
+---------+-------+----------+
| 1       | 2     | 59       |
| 2       | 1     | 11       |
| 1       | 3     | 20       |
| 3       | 4     | 100      |
| 3       | 4     | 200      |
| 3       | 4     | 200      |
| 4       | 3     | 499      |
+---------+-------+----------+

结果表:
+---------+---------+------------+----------------+
| person1 | person2 | call_count | total_duration |
+---------+---------+------------+----------------+
| 1       | 2       | 2          | 70             |
| 1       | 3       | 1          | 20             |
| 3       | 4       | 4          | 999            |
+---------+---------+------------+----------------+
用户 1 和 2 打过 2 次电话,总时长为 70 (59 + 11)。
用户 1 和 3 打过 1 次电话,总时长为 20。
用户 3 和 4 打过 4 次电话,总时长为 999 (100 + 200 + 200 + 499)。

建表+导数

create table 1842_Calls(from_id int, to_id int, duration int) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
load data inpath "/leetcode/1842_Calls" overwrite into table 1842_Calls;
select * from 1842_Calls

知识点:case进行行数据转换

select 
t.small_id person1, big_id person2, count(1) call_count, sum(t.duration) total_duration 
from 
(
	select
	case when from_id>to_id then to_id else from_id end small_id,
	case when from_id<to_id then to_id else from_id end big_id,
	duration
	from 1842_Calls
) t
group by t.small_id, big_id

执行结果: image.png

1852_Medium_访问日期之间最大的空档期

表:UserVisits

+-------------+------+
| Column Name | Type |
+-------------+------+
| user_id     | int  |
| visit_date  | date |
+-------------+------+
该表没有主键。
该表包含用户访问某特定零售商的日期日志。

假设今天的日期是'2021-1-1'

编写 SQL 语句,对于每个user_id,求出每次访问及其下一个访问(若该次访问是最后一次,则为今天)之间最大的空档期天数window

返回结果表,按用户编号user_id排序。

查询格式如下示例所示:

UserVisits 表:
+---------+------------+
| user_id | visit_date |
+---------+------------+
| 1       | 2020-11-28 |
| 1       | 2020-10-20 |
| 1       | 2020-12-3  |
| 2       | 2020-10-5  |
| 2       | 2020-12-9  |
| 3       | 2020-11-11 |
+---------+------------+
结果表:
+---------+---------------+
| user_id | biggest_window|
+---------+---------------+
| 1       | 39            |
| 2       | 65            |
| 3       | 51            |
+---------+---------------+
对于第一个用户,问题中的空档期在以下日期之间:
    - 2020-10-20  2020-11-28 ,共计 39 天。
    - 2020-11-28  2020-12-3 ,共计 5 天。
    - 2020-12-3  2021-1-1 ,共计 29 天。
由此得出,最大的空档期为 39 天。
对于第二个用户,问题中的空档期在以下日期之间:
    - 2020-10-5  2020-12-9 ,共计 65 天。
    - 2020-12-9  2021-1-1 ,共计 23 天。
由此得出,最大的空档期为 65 天。
对于第三个用户,问题中的唯一空档期在 2020-11-11  2021-1-1 之间,共计 51 天。

建表+导数

create table 1852_UserVisits(user_id int, visit_date date) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
load data inpath "/leetcode/1852_UserVisits" overwrite into table 1852_UserVisits;
select * from 1852_UserVisits

知识点:lead开窗,向窗口后取第n条

select 
tt.user_id, tt.date_diff biggest_window
from
(
	select
	t.user_id,
	date_diff,
	rank() over(partition by t.user_id order by date_diff desc) rk
	from 
	(
		select 
		user_id, 
		datediff(
		lead(visit_date,1,'2021-1-1') over(partition by user_id order by visit_date),
		visit_date
		) date_diff
		from 1852_UserVisits
	) t
) tt
where tt.rk=1

执行结果:

image.png

1862_Medium_苹果和橘子的个数

表:Boxes

+--------------+------+
| Column Name  | Type |
+--------------+------+
| box_id       | int  |
| chest_id     | int  |
| apple_count  | int  |
| orange_count | int  |
+--------------+------+
box_id 是该表的主键。
chest_id 是 chests 表的外键。
该表包含大箱子 (box) 中包含的苹果和橘子的个数。每个大箱子中可能包含一个小盒子 (chest) ,小盒子中也包含若干苹果和橘子。

表:Chests

+--------------+------+
| Column Name  | Type |
+--------------+------+
| chest_id     | int  |
| apple_count  | int  |
| orange_count | int  |
+--------------+------+
chest_id 是该表的主键。
该表包含小盒子的信息,以及小盒子中包含的苹果和橘子的个数。

编写 SQL 语句,查询每个大箱子中苹果和橘子的个数。如果大箱子中包含小盒子,还应当包含小盒子中苹果和橘子的个数。

以任意顺序返回结果表。

查询结果的格式如下示例所示:

Boxes 表:
+--------+----------+-------------+--------------+
| box_id | chest_id | apple_count | orange_count |
+--------+----------+-------------+--------------+
| 2      | null     | 6           | 15           |
| 18     | 14       | 4           | 15           |
| 19     | 3        | 8           | 4            |
| 12     | 2        | 19          | 20           |
| 20     | 6        | 12          | 9            |
| 8      | 6        | 9           | 9            |
| 3      | 14       | 16          | 7            |
+--------+----------+-------------+--------------+

Chests 表:
+----------+-------------+--------------+
| chest_id | apple_count | orange_count |
+----------+-------------+--------------+
| 6        | 5           | 6            |
| 14       | 20          | 10           |
| 2        | 8           | 8            |
| 3        | 19          | 4            |
| 16       | 19          | 19           |
+----------+-------------+--------------+

结果表:
+-------------+--------------+
| apple_count | orange_count |
+-------------+--------------+
| 151         | 123          |
+-------------+--------------+
大箱子 2 中有 6 个苹果和 15 个橘子。
大箱子 18 中有 4 + 20 (在小盒子中) = 24 个苹果和 15 + 10 (在小盒子中) = 25 个橘子。
大箱子 19 中有 8 + 19 (在小盒子中) = 27 个苹果和 4 + 4 (在小盒子中) = 8 个橘子。
大箱子 12 中有 19 + 8 (在小盒子中) = 27 个苹果和 20 + 8 (在小盒子中) = 28 个橘子。
大箱子 20 中有 12 + 5 (在小盒子中) = 17 个苹果和 9 + 6 (在小盒子中) = 15 个橘子。
大箱子 8 中有 9 + 5 (在小盒子中) = 14 个苹果和 9 + 6 (在小盒子中) = 15 个橘子。
大箱子 3 中有 16 + 20 (在小盒子中) = 36 个苹果和 7 + 10 (在小盒子中) = 17 个橘子。
苹果的总个数 = 6 + 24 + 27 + 27 + 17 + 14 + 36 = 151
橘子的总个数 = 15 + 25 + 8 + 28 + 15 + 15 + 17 = 123

建表+导数

create table 1862_Boxes(box_id int, chest_id int, apple_count int, orange_count int) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
load data inpath "/leetcode/1862_Boxes" overwrite into table 1862_Boxes;
select * from 1862_Boxes

create table 1862_Chests(chest_id int, apple_count int, orange_count int) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
load data inpath "/leetcode/1862_Chests" overwrite into table 1862_Chests;
select * from 1862_Chests

知识点:左连接+聚合

select 
b.box_id, b.apple_count+coalesce(c.apple_count,0) apple_count,
b.orange_count+coalesce(c.orange_count,0) orange_count
from 1862_Boxes b
left join 1862_Chests c
on b.chest_id=c.chest_id

执行结果:

image.png

1877_Easy_求关注者的数量

表:Followers

+-------------+------+
| Column Name | Type |
+-------------+------+
| user_id     | int  |
| follower_id | int  |
+-------------+------+
(user_id, follower_id) 是这个表的主键。
该表包含一个关注关系中关注者和用户的编号,其中关注者关注用户。

写出 SQL 语句,对于每一个用户,返回该用户的关注者数量。

user_id的顺序返回结果表。

查询结果的格式如下示例所示:

Followers 表:
+---------+-------------+
| user_id | follower_id |
+---------+-------------+
| 0       | 1           |
| 1       | 0           |
| 2       | 0           |
| 2       | 1           |
+---------+-------------+
结果表:
+---------+----------------+
| user_id | followers_count|
+---------+----------------+
| 0       | 1              |
| 1       | 1              |
| 2       | 2              |
+---------+----------------+
0 的关注者有 {1}
1 的关注者有 {0}
2 的关注者有 {0,1}

建表+导数

create table 1877_Followers(user_id int, follower_id int) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
load data inpath "/leetcode/1877_Followers" overwrite into table 1877_Followers;
select * from 1877_Followers

知识点:group by 搞定

select
user_id, count(1) followers_count
from 1877_Followers
group by user_id

执行结果: image.png

1908_Easy_可回收且低脂的产品

表:Products

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| product_id  | int     |
| low_fats    | enum    |
| recyclable  | enum    |
+-------------+---------+
product_id 是这个表的主键。
low_fats 是枚举类型,取值为以下两种 ('Y', 'N'),其中 'Y' 表示该产品是低脂产品,'N' 表示不是低脂产品。
recyclable 是枚举类型,取值为以下两种 ('Y', 'N'),其中 'Y' 表示该产品可回收,而 'N' 表示不可回收。

写出 SQL 语句,查找既是低脂又是可回收的产品编号。

返回结果 无顺序要求 。

查询结果格式如下例所示:

Products 表:
+-------------+----------+------------+
| product_id  | low_fats | recyclable |
+-------------+----------+------------+
| 0           | Y        | N          |
| 1           | Y        | Y          |
| 2           | N        | Y          |
| 3           | Y        | Y          |
| 4           | N        | N          |
+-------------+----------+------------+
Result 表:
+-------------+
| product_id  |
+-------------+
| 1           |
| 3           |
+-------------+
只有产品 id 为 13 的产品,既是低脂又是可回收的产品。

建表+导数

create table 1908_Products(product_id int, low_fats string, recyclable string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
load data inpath "/leetcode/1908_Products" overwrite into table 1908_Products;
select * from 1908_Products

知识点:where 条件过滤

select product_id
from 1908_Products
where low_fats='Y' and recyclable='Y'

执行结果:

image.png

1926_Easy_每家商店的产品价格

表:Products

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| product_id  | int     |
| store       | enum    |
| price       | int     |
+-------------+---------+
(product_id,store) 是这个表的主键。
store 字段是枚举类型,它的取值为以下三种 ('store1', 'store2', 'store3') 。
price 是该商品在这家商店中的价格。

写出一个 SQL 查询语句,查找每种产品在各个商店中的价格。

可以以 任何顺序 输出结果。

查询结果格式如下例所示:

Products 表:
+-------------+--------+-------+
| product_id  | store  | price |
+-------------+--------+-------+
| 0           | store1 | 95    |
| 0           | store3 | 105   |
| 0           | store2 | 100   |
| 1           | store1 | 70    |
| 1           | store3 | 80    |
+-------------+--------+-------+
Result 表:
+-------------+--------+--------+--------+
| product_id  | store1 | store2 | store3 |
+-------------+--------+--------+--------+
| 0           | 95     | 100    | 105    |
| 1           | 70     | null   | 80     |
+-------------+--------+--------+--------+
产品 0 的价格在商店 195 ,商店 2100 ,商店 3105 。
产品 1 的价格在商店 170 ,商店 3 的产品 1 价格为 80 ,但在商店 2 中没有销售。

建表+导数

create table 1926_Products(product_id int, store string, price int) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
load data inpath "/leetcode/1962_Products" overwrite into table 1926_Products;
select * from 1926_Products

知识点:grpup by sum

select 
product_id, 
sum(case when store='store1' then price end)  store1,
sum(case when store='store2' then price end) store2,
sum(case when store='store3' then price end) store3
from 1926_Products
group by product_id

执行结果:

image.png