目录
聚合函数
620. 有趣的电影
表:cinema
+----------------+----------+
| Column Name | Type |
+----------------+----------+
| id | int |
| movie | varchar |
| description | varchar |
| rating | float |
+----------------+----------+
id 是该表的主键(具有唯一值的列)。
每行包含有关电影名称、类型和评级的信息。
评级为 [0,10] 范围内的小数点后 2 位浮点数。
编写解决方案,找出所有影片描述为 非 boring
(不无聊) 的并且 id 为奇数 的影片。
返回结果按 rating
降序排列。
结果格式如下示例。
示例 1:
输入:
+---------+-----------+--------------+-----------+
| id | movie | description | rating |
+---------+-----------+--------------+-----------+
| 1 | War | great 3D | 8.9 |
| 2 | Science | fiction | 8.5 |
| 3 | irish | boring | 6.2 |
| 4 | Ice song | Fantacy | 8.6 |
| 5 | House card| Interesting| 9.1 |
+---------+-----------+--------------+-----------+
输出:
+---------+-----------+--------------+-----------+
| id | movie | description | rating |
+---------+-----------+--------------+-----------+
| 5 | House card| Interesting| 9.1 |
| 1 | War | great 3D | 8.9 |
+---------+-----------+--------------+-----------+
解释:
我们有三部电影,它们的 id 是奇数:1、3 和 5。id = 3 的电影是 boring 的,所以我们不把它包括在答案中。
select *
from cinema
where mod(id, 2) = 1 and description != 'boring'
order by rating DESC
;
-
mod(id, 2) = 1
:使用MOD
函数判断电影 ID 是否为奇数。MOD(id, 2)
返回id
除以 2 的余数,余数为 1 表示 ID 是奇数。该条件用于筛选出奇数 ID 的电影(通常对应单号座位或场次)。 -
description != 'boring'
:排除描述为'boring'
(乏味)的电影,确保只返回描述不为乏味的记录。 -
ORDER BY rating DESC
表示按电影评分(rating
列)进行降序排列,评分最高的电影排在最前。
1251. 平均售价
表:Prices
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| product_id | int |
| start_date | date |
| end_date | date |
| price | int |
+---------------+---------+
(product_id,start_date,end_date) 是 prices 表的主键(具有唯一值的列的组合)。
prices 表的每一行表示的是某个产品在一段时期内的价格。
每个产品的对应时间段是不会重叠的,这也意味着同一个产品的价格时段不会出现交叉。
表:UnitsSold
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| product_id | int |
| purchase_date | date |
| units | int |
+---------------+---------+
该表可能包含重复数据。
该表的每一行表示的是每种产品的出售日期,单位和产品 id。
编写解决方案以查找每种产品的平均售价。average_price
应该 四舍五入到小数点后两位。如果产品没有任何售出,则假设其平均售价为 0。
返回结果表 无顺序要求 。
结果格式如下例所示。
示例 1:
输入:
Prices table:
+------------+------------+------------+--------+
| product_id | start_date | end_date | price |
+------------+------------+------------+--------+
| 1 | 2019-02-17 | 2019-02-28 | 5 |
| 1 | 2019-03-01 | 2019-03-22 | 20 |
| 2 | 2019-02-01 | 2019-02-20 | 15 |
| 2 | 2019-02-21 | 2019-03-31 | 30 |
+------------+------------+------------+--------+
UnitsSold table:
+------------+---------------+-------+
| product_id | purchase_date | units |
+------------+---------------+-------+
| 1 | 2019-02-25 | 100 |
| 1 | 2019-03-01 | 15 |
| 2 | 2019-02-10 | 200 |
| 2 | 2019-03-22 | 30 |
+------------+---------------+-------+
输出:
+------------+---------------+
| product_id | average_price |
+------------+---------------+
| 1 | 6.96 |
| 2 | 16.96 |
+------------+---------------+
解释:
平均售价 = 产品总价 / 销售的产品数量。
产品 1 的平均售价 = ((100 * 5)+(15 * 20) )/ 115 = 6.96
产品 2 的平均售价 = ((200 * 15)+(30 * 30) )/ 230 = 16.96
SELECT
product_id,
IFNULL(Round(SUM(sales) / SUM(units), 2), 0) AS average_price
FROM (
SELECT
Prices.product_id AS product_id,
Prices.price * UnitsSold.units AS sales,
UnitsSold.units AS units
FROM Prices
LEFT JOIN UnitsSold ON Prices.product_id = UnitsSold.product_id
AND (UnitsSold.purchase_date BETWEEN Prices.start_date AND Prices.end_date)
) T
GROUP BY product_id
-
方法一:JOIN
-
思路:本题需要计算每个产品的平均售价,平均售价 = 销售总额 / 总数量,因此我们只需要计算除每个产品的销售总额和总数量即可。
-
总数量可以直接使用 UnitsSold 计算得出,使用 GROUP BY 和 SUM 函数即可:
SELECT product_id, SUM(units) FROM UnitsSold GROUP BY product_id
-
因为每个产品不同时期的售价不同,因此在计算销售总额之前要先分别计算每个价格的销售总额。每个价格的销售总额为 对应时间内的价格∗对应时间内的数量。因为价格和时间在 Prices 表中,数量在 UnitsSold 表中,这两个表通过 product_id 关联,那么我们就可以使用 LEFT JOIN 将两个表连接,通过 WHERE 查询对应时间内每个产品的价格和数量,并计算出对应的销售总额。
SELECT Prices.product_id AS product_id, Prices.price * UnitsSold.units AS sales, UnitsSold.units AS units FROM Prices LEFT JOIN UnitsSold ON Prices.product_id = UnitsSold.product_id AND (UnitsSold.purchase_date BETWEEN Prices.start_date AND Prices.end_date)
-
计算出产品每个价格的销售总额后,同样的使用 SUM 函数计算出产品所有时间的销售总额,然后除以总数量并使用 ROUND 函数保留两位小数即可。
-
1075. 项目员工 I
项目表 Project
:
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| project_id | int |
| employee_id | int |
+-------------+---------+
主键为 (project_id, employee_id)。
employee_id 是员工表 Employee 表的外键。
这张表的每一行表示 employee_id 的员工正在 project_id 的项目上工作。
员工表 Employee
:
+------------------+---------+
| Column Name | Type |
+------------------+---------+
| employee_id | int |
| name | varchar |
| experience_years | int |
+------------------+---------+
主键是 employee_id。数据保证 experience_years 非空。
这张表的每一行包含一个员工的信息。
请写一个 SQL 语句,查询每一个项目中员工的 平均 工作年限,精确到小数点后两位。
以 任意 顺序返回结果表。
查询结果的格式如下:
示例 1:
输入:
Project 表:
+-------------+-------------+
| project_id | employee_id |
+-------------+-------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 4 |
+-------------+-------------+
Employee 表:
+-------------+--------+------------------+
| employee_id | name | experience_years |
+-------------+--------+------------------+
| 1 | Khaled | 3 |
| 2 | Ali | 2 |
| 3 | John | 1 |
| 4 | Doe | 2 |
+-------------+--------+------------------+
输出:
+-------------+---------------+
| project_id | average_years |
+-------------+---------------+
| 1 | 2.00 |
| 2 | 2.50 |
+-------------+---------------+
解释:第一个项目中,员工的平均工作年限是 (3 + 2 + 1) / 3 = 2.00;第二个项目中,员工的平均工作年限是 (3 + 2) / 2 = 2.50
-
每一个项目中员工(GROUP BY分组)
-
平均工作年限(AVG函数)
-
精确到小数点后两位(ROUND函数)
SELECT
project_id,
ROUND(AVG(e.experience_years),2) AS average_years
FROM
Project as p
LEFT JOIN
Employee as e
ON
p.employee_id = e.employee_id
GROUP BY
p.project_id;
1633. 各赛事的用户注册率
用户表: Users
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| user_id | int |
| user_name | varchar |
+-------------+---------+
user_id 是该表的主键(具有唯一值的列)。
该表中的每行包括用户 ID 和用户名。
注册表: Register
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| contest_id | int |
| user_id | int |
+-------------+---------+
(contest_id, user_id) 是该表的主键(具有唯一值的列的组合)。
该表中的每行包含用户的 ID 和他们注册的赛事。
编写解决方案统计出各赛事的用户注册百分率,保留两位小数。
返回的结果表按 percentage
的 降序 排序,若相同则按 contest_id
的 升序 排序。
返回结果如下示例所示。
示例 1:
输入:
Users 表:
+---------+-----------+
| user_id | user_name |
+---------+-----------+
| 6 | Alice |
| 2 | Bob |
| 7 | Alex |
+---------+-----------+
Register 表:
+------------+---------+
| contest_id | user_id |
+------------+---------+
| 215 | 6 |
| 209 | 2 |
| 208 | 2 |
| 210 | 6 |
| 208 | 6 |
| 209 | 7 |
| 209 | 6 |
| 215 | 7 |
| 208 | 7 |
| 210 | 2 |
| 207 | 2 |
| 210 | 7 |
+------------+---------+
输出:
+------------+------------+
| contest_id | percentage |
+------------+------------+
| 208 | 100.0 |
| 209 | 100.0 |
| 210 | 100.0 |
| 215 | 66.67 |
| 207 | 33.33 |
+------------+------------+
解释:
所有用户都注册了 208、209 和 210 赛事,因此这些赛事的注册率为 100% ,我们按 contest_id 的降序排序加入结果表中。
Alice 和 Alex 注册了 215 赛事,注册率为 ((2/3) * 100) = 66.67%
Bob 注册了 207 赛事,注册率为 ((1/3) * 100) = 33.33%
-
首先我们观察这两个表以及问题,可以发现:
-
不同赛事是需要进行分别统计的
-
两个表虽然有共同的字段,但是并不需要连接。
-
因为统计一门赛事注册的user_id在Register表中
-
统计user_id总数量在Users表中
-
两者都是可以独立查询出来的
-
-
-
那么梳理一下做题步骤:
-
不同赛事进行分组
-
分别统计一门赛事中注册了的user_id数量、user_id总数量
-
保留两位小数
-
结果按percentage降序排序,相同按contest_id的升序排序
-
# Write your MySQL query statement below
select contest_id , round(count(user_id) * 100/ (select count(*) from users), 2) percentage
from Register
group by contest_id
order by percentage desc, contest_id
1211. 查询结果的质量和占比
Queries
表:
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| query_name | varchar |
| result | varchar |
| position | int |
| rating | int |
+-------------+---------+
此表可能有重复的行。
此表包含了一些从数据库中收集的查询信息。
“位置”(position)列的值为 1 到 500 。
“评分”(rating)列的值为 1 到 5 。评分小于 3 的查询被定义为质量很差的查询。
将查询结果的质量 quality
定义为:
各查询结果的评分与其位置之间比率的平均值。rating/position
将劣质查询百分比 poor_query_percentage
定义为:
评分小于 3 的查询结果占全部查询结果的百分比。
编写解决方案,找出每次的 query_name
、 quality
和 poor_query_percentage
。
quality
和 poor_query_percentage
都应 四舍五入到小数点后两位 。
以 任意顺序 返回结果表。
结果格式如下所示:
示例 1:
输入:
Queries table:
+------------+-------------------+----------+--------+
| query_name | result | position | rating |
+------------+-------------------+----------+--------+
| Dog | Golden Retriever | 1 | 5 |
| Dog | German Shepherd | 2 | 5 |
| Dog | Mule | 200 | 1 |
| Cat | Shirazi | 5 | 2 |
| Cat | Siamese | 3 | 3 |
| Cat | Sphynx | 7 | 4 |
+------------+-------------------+----------+--------+
输出:
+------------+---------+-----------------------+
| query_name | quality | poor_query_percentage |
+------------+---------+-----------------------+
| Dog | 2.50 | 33.33 |
| Cat | 0.66 | 33.33 |
+------------+---------+-----------------------+
解释:
Dog 查询结果的质量为 ((5 / 1) + (5 / 2) + (1 / 200)) / 3 = 2.50
Dog 查询结果的劣质查询百分比为 (1 / 3) * 100 = 33.33
Cat 查询结果的质量为 ((2 / 5) + (3 / 3) + (4 / 7)) / 3 = 0.66
Cat 查询结果的劣质查询百分比为 (1 / 3) * 100 = 33.33
select
query_name,
round(avg(rating/position),2) quality,
round(100 * avg(rating < 3),2) poor_query_percentage
from
Queries
group by
query_name;
-
avg(rating < 3)
-
针对每一条记录,判断
rating < 3
这个条件是否成立,成立则记为1
,不成立则记为0
。 -
对所有记录的判断结果进行求和。
-
用求和的结果除以记录的总数,得到平均值,这个平均值就是低质量查询的比例。
-