LeetCode sql题解 6 (按照面试出现频率)

1082. 销售分析 I

产品表:Product

Column Name Type
product_id int
product_name varchar
unit_price int

product_id 是这个表的主键.
销售表:Sales

Column Name Type
seller_id int
product_id int
buyer_id int
sale_date date
quantity int
price int

这个表没有主键,它可以有重复的行.
product_id 是 Product 表的外键.

编写一个 SQL 查询,查询总销售额最高的销售者,如果有并列的,就都展示出来。

查询结果格式如下所示:

Product 表:

product_id product_name unit_price
1 S8 1000
2 G4 800
3 iPhone 1400

Sales 表:

seller_id product_id buyer_id sale_date quantity price
1 1 1 2019-01-21 2 2000
1 2 2 2019-02-17 1 800
2 2 3 2019-06-02 1 800
3 3 4 2019-05-13 2 2800

Result 表:

seller_id
1
3

Id 为 1 和 3 的销售者,销售总金额都为最高的 2800。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sales-analysis-i
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路

  1. 统计每个销售员的总业绩
SELECT
	seller_id,
	sum( price ) AS yeji 
FROM
	Sales 
GROUP BY
	seller_id;
  1. 然后找到最高的业绩
SELECT
	sum( price ) AS ye_ji 
FROM
	Sales 
GROUP BY
	seller_id 
ORDER BY
	ye_ji DESC 
	LIMIT 1
  1. 从原始表中找到业绩与这个最高业绩相等的 seller_id
SELECT
	seller_id 
FROM
	sales 
GROUP BY
	seller_id 
HAVING
	SUM( price ) = ( SELECT max( sales_total ) FROM ( SELECT seller_id, SUM( price ) AS sales_total FROM sales GROUP BY seller_id ) sub1 )

1098.小众书籍

书籍表 Books:

Column Name Type
book_id int
name varchar
available_from date

book_id 是这个表的主键。
订单表 Orders:

Column Name Type
order_id int
book_id int
quantity int
dispatch_date date

order_id 是这个表的主键。
book_id 是 Books 表的外键。

你需要写一段 SQL 命令,筛选出订单总量 少于10本 的 书籍 。

注意:不考虑 上架(available from)距今 不满一个月 的书籍。并且 假设今天是 2019-06-23 。

下面是样例输出结果:

Books 表:

book_id name available_from
1 “Kalila And Demna” 2010-01-01
2 “28 Letters” 2012-05-12
3 “The Hobbit” 2019-06-10
4 “13 Reasons Why” 2019-06-01
5 “The Hunger Games” 2008-09-21

Orders 表:

order_id book_id quantity dispatch_date
1 1 2 2018-07-26
2 1 1 2018-11-05
3 3 8 2019-06-11
4 4 6 2019-06-05
5 4 5 2019-06-20
6 5 9 2009-02-02
7 5 8 2010-04-13

Result 表:

book_id name
1 “Kalila And Demna”
2 “28 Letters”
5 “The Hunger Games”

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unpopular-books
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
中文翻译少了个条件(距今一年内的销量)

SELECT
	book_id,
	SUM( quantity ) 
FROM
	orders 
WHERE
	dispatch_date BETWEEN '2018-06-23' 
	AND '2019-06-23' 
GROUP BY
	book_id 
HAVING
	SUM( quantity ) >= 10

512.游戏玩法分析

Table: Activity

Column Name Type
player_id int
device_id int
event_date date
games_played int

(player_id, event_date) 是这个表的两个主键
这个表显示的是某些游戏玩家的游戏活动情况
每一行是在某天使用某个设备登出之前登录并玩多个游戏(可能为0)的玩家的记录
请编写一个 SQL 查询,描述每一个玩家首次登陆的设备名称

查询结果格式在以下示例中:

Activity table:

player_id device_id event_date games_played
1 2 2016-03-01 5
1 2 2016-05-02 6
2 3 2017-06-25 1
3 1 2016-03-02 0
3 4 2018-07-03 5

Result table:

player_id device_id
1 2
2 3
3 1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/game-play-analysis-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路

  1. 首先使用 min 函数和group by函数找到所有玩家初次玩游戏的时间
 SELECT
	player_id,
	min( event_date ) AS first_login 
FROM
	Activity 
GROUP BY
	player_id
  1. 将1作为子查询,外层在套用一层,查找player_id 和 device_id
SELECT
	player_id,
	min( event_date ) AS first_login 
FROM
	Activity 
GROUP BY
	player_id; SELECT
	a.player_id,
	a.device_id 
FROM
	Activity a 
WHERE
	( a.player_id, a.event_date ) IN ( SELECT player_id, min( event_date ) AS first_login FROM Activity GROUP BY player_id )

626.换座位

小美是一所中学的信息科技老师,她有一张 seat 座位表,平时用来储存学生名字和与他们相对应的座位 id。

其中纵列的 id 是连续递增的

小美想改变相邻俩学生的座位。

你能不能帮她写一个 SQL query 来输出小美想要的结果呢?

示例:

id student
1 Abbot
2 Doris
3 Emerson
4 Green
5 Jeames

假如数据输入的是上表,则输出结果如下:

id student
1 Doris
2 Abbot
3 Green
4 Emerson
5 Jeames

注意:

如果学生人数是奇数,则不需要改变最后一个同学的座位

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/exchange-seats
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
通过改变id实现换座位

SELECT
	(
	CASE
			
			WHEN id % 2 = 0 THEN
			id - 1 
			WHEN id = ( SELECT MAX( id ) FROM seat ) THEN
			id ELSE id + 1 
		END 
		) AS id,
		student 
	FROM
		seat 
ORDER BY
	id

1045.买下所有产品的客户

Customer 表:

Column Name Type
customer_id int
product_key int

product_key 是 Product 表的外键。
Product 表:

Column Name Type
product_key int

product_key 是这张表的主键。

写一条 SQL 查询语句,从 Customer 表中查询购买了 Product 表中所有产品的客户的 id。

示例:

Customer 表:

customer_id product_key
1 5
2 6
3 5
3 6
1 6

Product 表:

product_key
5
6

Result 表:

customer_id
1
3

购买了所有产品(5 和 6)的客户的 id 是 1 和 3 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/customers-who-bought-all-products
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
比较customer表中去重之后的商品key是否等于商品表中的记录数

SELECT
	customer_id 
FROM
	customer 
GROUP BY
	customer_id 
HAVING
	count( DISTINCT product_key ) = ( SELECT count( DISTINCT product_key ) FROM product )

505.游戏玩法分析

Table: Activity

Column Name Type
player_id int
device_id int
event_date date
games_played int

(player_id,event_date)是此表的主键。
这张表显示了某些游戏的玩家的活动情况。
每一行是一个玩家的记录,他在某一天使用某个设备注销之前登录并玩了很多游戏(可能是 0)。

编写一个 SQL 查询,报告在首次登录的第二天再次登录的玩家的分数,四舍五入到小数点后两位。换句话说,您需要计算从首次登录日期开始至少连续两天登录的玩家的数量,然后除以玩家总数。

查询结果格式如下所示:

Activity table:

player_id device_id event_date games_played
1 2 2016-03-01 5
1 2 2016-03-02 6
2 3 2017-06-25 1
3 1 2016-03-02 0
3 4 2018-07-03 5

Result table:

fraction
0.33

只有 ID 为 1 的玩家在第一天登录后才重新登录,所以答案是 1/3 = 0.33

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/game-play-analysis-iv
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

-- 首次登陆
SELECT player_id,min(EVENT_date) FIRST_date FROM activity
GROUP BY player_id;
-- 将首次登陆作为临时表
SELECT * FROM
activity a,
(SELECT player_id,min(event_date) first_date FROM
activity GROUP BY player_id) b
WHERE a.player_id = b.player_id;
-- 求日期差
SELECT DATEDIFF(a.event_date, b.first_date),
(SELECT COUNT(DISTINCT (player_id)) FROM activity)
FROM activity a,
(SELECT player_id,MIN(event_date) first_date FROM activity
GROUP BY player_id) b
WHERE a.player_id = b.player_id;
-- case when then else 过滤符合条件的玩家
SELECT SUM(case WHEN DATEDIFF(a.event_date, b.first_date)=1 THEN 1 ELSE 0 end),
(SELECT COUNT(DISTINCT (player_id)) FROM activity) FROM activity a,
(SELECT player_id,MIN(event_date) first_date FROM activity 
GROUP BY player_id) b
WHERE a.player_id=b.player_id
select round(sum(case when datediff(a.event_date,b.first_date)=1 then 1 else 0 end)/(select count(distinct(player_id)) from activity),2) as fraction
from activity a,
(select player_id,min(event_date) first_date from activity group by player_id) b
where a.player_id=b.player_id

619.只出现一次的最大数字

表 my_numbers 的 num 字段包含很多数字,其中包括很多重复的数字。

你能写一个 SQL 查询语句,找到只出现过一次的数字中,最大的一个数字吗?

num
8
8
3
3
1
4
5
6

对于上面给出的样例数据,你的查询语句应该返回如下结果:

num
6

注意:

如果没有只出现一次的数字,输出 null 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/biggest-single-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

SELECT MAX(num) num FROM
(SELECT * FROM my_numbers
GROUP BY Num
HAVING COUNT(num)=1) s

603.连续空余的座位几个朋友来到电影院的售票处,准备预约连续空余座位。

你能利用表 cinema ,帮他们写一个查询语句,获取所有空余座位,并将它们按照 seat_id 排序后返回吗?

seat_id free
1 1
2 0
3 1
4 1
5 1

对于如上样例,你的查询语句应该返回如下结果。

seat_id
3
4
5

注意:

seat_id 字段是一个自增的整数,free 字段是布尔类型(‘1’ 表示空余, ‘0’ 表示已被占据)。
连续空余座位的定义是大于等于 2 个连续空余的座位。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/consecutive-available-seats
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

SELECT DISTINCT a.seat_id FROM cinema a
join cinema b
on abs(a.seat_id-b.seat_id)=1
AND a.free = true AND b.free = TRUE
ORDER BY a.seat_id

你可能感兴趣的:(数据库,SQL,Leetcode题解)