LeetCode SQL 刷题
文章目录
- MySQL配置
- 数据库准备
- 1. 大国
- 2. 换座位
- 2.1 solution-1
- 2.2 solution-2
- 3. 交换工资
- solution-1
- 4. 有趣的电影
- solution
- 5. 超过5名学生的课
- solution-1 group by + having
- solution-2 group by + 子查询
- 6. 查找重复的电子邮箱
- 7. 删除重复的电子邮箱
- solutionn-1 子查询
- solution-2 自连接
- 8. 组合两个表
- 9. 超过经理收入的员工
- 10. 从不订购的客户
- solution1 子查询
- solution2 左连接 + null值判断
- 11. 部门工资最高的员工
- 12. 第二高的薪水
- 13. 编写一个 SQL 查询,获取 Employee 表中第 n 高的薪水(Salary)。
- 14. 分数排名
- 15. 补充-1 分段统计 贝壳面试题
MySQL配置
关闭safe updates模式,该模式下非键条件(wehre字段不是key)无法执行update和delete
show variables like ‘sql_safe_updates’;
set sql_safe_updates = ‘off’;only_full_group_by
5.7默认开启,该模式下,select和order by等所涉及的字段必须在group by中出现过。查询字段含有聚合函数除外,例如select count(xx).
谨慎使用select any_value(xx),
例如 select any_value(a), b from table gorup by b;
该查询只会返回一个分组结果,对于若b分组内有多个a,其只会随机返回一个,而不是返回该分组下的所有记录。
数据库准备
- 创建干净的数据库
drop database if exists leetcode;
create database leetcode;
use leetcode;
1. 大国
如果一个国家的面积超过300万平方公里,或者人口超过2500万,那么这个国家就是大国家。
编写一个SQL查询,输出表中所有大国家的名称、人口和面积。
schema
drop table if exists World;
CREATE TABLE World (name VARCHAR(255),continent VARCHAR(255),area INT,population INT,gdp INT
);
insert into World (name, continent, area, population, gdp)
values ('Afghanistan', 'Asia', '652230', '25500100', '20343000'),('Albania', 'Europe', '28748', '2831741', '12960000'),('Algeria', 'Africa', '2381741', '37100000', '188681000'),('Andorra', 'Europe', '468', '78115', '3712000'),('Angola', 'Africa', '1246700', '20609294', '100990000');
solution
SELECT name, population, area
FROMWorld
WHEREarea > 3000000 OR population > 25000000;
2. 换座位
小美是一所中学的信息科技老师,她有一张 seat 座位表,平时用来储存学生名字和与他们相对应的座位 id。
其中纵列的 id 是连续递增的
小美想改变相邻俩学生的座位。
如果学生人数是奇数,则不需要改变最后一个同学的座位。
ps:调换1-2,3-4…的座位上的学生。
schema
create table if not exists seat (id int unique,student varchar(255)
);
truncate table seat;
insert into seat (id, student) values('1', 'Abbot'),('2', 'Doris'),('3', 'Emerson'), ('4', 'Green'),('5', 'Jeames');
2.1 solution-1
使用case when
CASE WHEN THEN ELSE END语法
Case具有两种格式。简单Case函数和Case搜索函数。
--简单Case函数
CASE sexWHEN '1' THEN '男'WHEN '2' THEN '女'
ELSE '其他' END
--Case搜索函数
CASE WHEN sex = '1' THEN '男'WHEN sex = '2' THEN '女'
ELSE '其他' END
Case会返回第一个符合条件的值,需要注意的是,需要使用AS指定CASE语句的列名,否则该列的名称将会为CASE语句本身。
# 交换操作 = 偶数id自减,奇数id自增(最后一个除外)
SELECT (CASEWHEN id % 2 != 0 AND seat_counts.counts != id THEN id + 1WHEN MOD(id, 2) != 0 AND counts = id THEN idELSE id - 1END) AS id,student
FROMseat,(SELECT # 内联视图(SELECT产生的临时表),SELECT结果作为seat_counts 表COUNT(*) AS counts # COUNT函数结果作为counts列值FROMseat) AS seat_counts
ORDER BY id ASC;
2.2 solution-2
使用union
UNION语法
UNION用于合并多个SELECT执行结果,SELECT的列数相同、列数据类型相似。结果集的列名等于第一个SELECT中的列名。UNION会剔除相同的值,UNION ALL允许有重复值。
SELECT column_name(s) FROM table1
UNION
SELECT column_name(s) FROM table2;
使用UNION合并多个情况的查询结果
SELECT id - 1 AS id, student FROM seat WHERE id % 2 = 0
UNION SELECT id + 1, student FROM seat WHERE id % 2 != 0AND id != (SELECT MAX(id) FROM seat)
UNION SELECT id, student FROM seat WHERE id % 2 != 0AND id = (SELECT MAX(id) FROM seat)
ORDER BY id ASC;
3. 交换工资
给定一个 salary表,如下所示,有m=男性 和 f=女性的值 。交换所有的 f 和 m 值
(例如,将所有 f 值更改为 m,反之亦然)。要求使用一个更新查询,并且没有中间临时表。
schema
create table if not exists salary (id int,name varchar(255),sex char(1),salary int
);
truncate table salary;
insert into salary (id, name, sex, salary) values(1, 'A', 'm', 2500),(2, 'B', 'f', 1500),(3, 'C', 'm', 5500),(4, 'D', 'f', 500);
solution-1
update salary set sex = (case sex when 'm' then 'f'when 'f' then 'm'end);
4. 有趣的电影
某城市开了一家新的电影院,吸引了很多人过来看电影。该电影院特别注意用户体验,专门有个 LED显示板做电影推荐,上面公布着影评和相关电影描述。
作为该电影院的信息部主管,您需要编写一个 SQL查询,
找出所有影片描述为非 boring (不无聊) 的并且 id 为奇数 的影片,
结果请按等级 rating 排列。
schema
create table if not exists cinema (id int8 primary key, # int 有 1 2 4 8字节movie varchar(255),description varchar(255),rating float(2, 1) # 浮点数可指定精度,(2,1)表示小数点后一位共两位,例如1.3
);
truncate table cinema;
insert into cinema (id, movie, description, rating) values ('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');
solution
SELECT id, movie, description, rating
FROMcinema
WHEREdescription != 'boring' AND id % 2 != 0
ORDER BY rating DESC;
5. 超过5名学生的课
有一个courses 表 ,有: student (学生) 和 class (课程)。
请列出所有超过或等于5名学生的课。
schema
create table if not exists courses (student varchar(255),class varchar(255)
);
truncate table courses;
insert into courses (student, class) values ('A', 'Math'),('B', 'English'),('C', 'Math'),('D', 'Biology'),('E', 'Math'),('F', 'Computer'),('G', 'Math'),('H', 'Math'),('I', 'Math');
列出每门课的学生(已去除重复记录)
SELECT class, COUNT(DISTINCT student) AS stu_count # count计数,sum累加
FROMcourses
GROUP BY class; # group by用于对结果集进行分组,将相同值的列放在同一组中。若无,则COUNT列统计所有列。
solution-1 group by + having
SELECT class
FROMcourses
GROUP BY class
HAVING COUNT(DISTINCT student) >= 5; # where过滤行,having过滤分组
solution-2 group by + 子查询
SELECT class
FROM(SELECT class, COUNT(DISTINCT student) AS stu_countFROMcoursesGROUP BY class) AS temp # 使用子查询统计每门课的学生数量
WHEREstu_count >= 5;
6. 查找重复的电子邮箱
编写一个 SQL 查询,查找 Person 表中所有重复的电子邮箱。
create table if not exists Person (Id int8 primary key,Email varchar(255)
);
truncate table Person;
insert into Person (Id, Email) values ('1', 'a@b.com'),('2', 'c@d.com'),('3', 'a@b.com');
**solution **
# 分组统计每个Email的ID数,找出大于1的。
SELECT Email
FROMPerson
GROUP BY Email
HAVING COUNT(Id) >= 2;
7. 删除重复的电子邮箱
编写一个 SQL 查询,来删除 Person 表中所有重复的电子邮箱,
重复的邮箱里只保留 Id 最小 的那个。
schema
create table if not exists Person (Id int8 primary key,Email varchar(255)
);
truncate table Person;
insert into Person (Id, Email) values ('1', 'john@example.com'),('2', 'bob@example.com'),('3', 'john@example.com');
solutionn-1 子查询
先按照Email分组,查询min(id),然后删除非min(id)的记录。
/**
错误写法
You can't specify target table 'Person' for update in FROM clause
在MySQL中,不能先select出同一表中的某些值,再更新这个表(在同一语句中) **/
DELETE FROM Person
WHEREId NOT IN (SELECT MIN(Id) FROM Person GROUP BY Email);/**
正确写法,在嵌套一个子查询
**/
DELETE FROM Person
WHEREId NOT IN (SELECT Id FROM (SELECT MIN(id) AS Id FROM Person GROUP BY Email) AS temp);
solution-2 自连接
/**
隐式连接“,”等同于内连接inner join(简写join)。
内连接扫描左表的每一行,将其与右表的每一行比较,
符合连接条件时,返回由这两行组成的新行。
**/
DELETE p1
FROMPerson p1,Person p2
WHEREp1.Email = p2.Email AND p1.Id > p2.Id; # Email相等的行中(分组效果),ID较大者。
8. 组合两个表
编写一个 SQL 查询,满足条件:无论 person 是否有地址信息,
都需要基于上述两表提供 person 的以下信息:
FirstName, LastName, City, State
schema
drop table Person;
create table Person (PersonId int8 primary key,FirstName varchar(255),LastName varchar(255)
);
drop table Address;
create table Address (AddressId int8 primary key,PersonId int,City varchar(255),State varchar(255)
);
insert into Person (PersonId, LastName, FirstName) values ('1', 'Wang', 'Allen');
insert into Address (AddressId, PersonId, City, State) values ('1', '2', 'New York City', 'New York');
solution 左连接,返回左表所有数据。
SELECT FirstName, LastName, City, State
FROMPerson pLEFT JOINAddress a ON p.PersonId = a.PersonId;
9. 超过经理收入的员工
Employee 表包含所有员工,他们的经理也属于员工。每个员工都有一个 Id,
此外还有一列对应员工的经理的 Id。
给定 Employee 表,编写一个 SQL 查询,该查询可以获取收入超过他们经理的员工的姓名。
schema
create table if not exists Employee (Id int8 primary key,Name varchar(255),Salary varchar(255),ManagerId int
);
truncate table Employee;
insert into Employee (Id, Name, Salary, ManagerId) values ('1', 'Joe', '70000', '3'),('2', 'Henry', '80000', '4'),('3', 'Sam', '60000', null),('4', 'Max', '90000', null);
solution 自连接
SELECT e1.Name AS Employee
FROMEmployee AS e1INNER JOINEmployee e2 ON e1.ManagerId = e2.IdAND e1.Salary > e2.Salary;
10. 从不订购的客户
某网站包含两个表,Customers 表和 Orders 表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。
shcema
create table if not exists Customers (Id int8 primary key,Name varchar(255)
);
truncate table Customers;
create table if not exists Orders (Id int8 primary key,CustomerId int
);
truncate table Orders;
insert into Customers (Id, Name) values ('1', 'Joe');
insert into Customers (Id, Name) values ('2', 'Henry');
insert into Customers (Id, Name) values ('3', 'Sam');
insert into Customers (Id, Name) values ('4', 'Max');
insert into Orders (Id, CustomerId) values ('1', '3');
insert into Orders (Id, CustomerId) values ('2', '1');
solution1 子查询
SELECT Name AS Customers
FROMCustomers
WHEREid NOT IN (SELECT CustomerId FROM Orders);
solution2 左连接 + null值判断
/**
on条件:生成临时表的条件
where条件:在生成的临时表中的过滤条件
null值判断:使用is或者is not,不能使用=。null与其它值均不相等,包括null。
**/
SELECT *
FROMCustomers cLEFT JOINOrders o ON c.Id = o.CustomerId
WHEREo.CustomerId IS NULL
;
11. 部门工资最高的员工
Employee 表包含所有员工信息,每个员工有其对应的 Id, salary 和 department Id。
Department 表包含公司所有部门的信息。
编写一个 SQL 查询,找出每个部门工资最高的员工。
schema
drop table if exists Employee;
create table Employee (Id int8 primary key,Name varchar(255),Salary int8,DepartmentId int8
);
drop table if exists Department;
Create table If Not Exists Department (Id int, Name varchar(255));
INSERT INTO Employee ( Id, NAME, Salary, DepartmentId )
VALUES( 1, 'Joe', 70000, 1 ),( 2, 'Henry', 80000, 2 ),( 3, 'Sam', 60000, 2 ),( 4, 'Max', 90000, 1 );
INSERT INTO Department ( Id, NAME )
VALUES( 1, 'IT' ),( 2, 'Sales' );
错误解法 包含非group by字段,返回结果不确定
select any_value(d.Name) as Department, any_value(e.Name) as Employee, max(e.Salary)
from Employee e
left join Department d on e.DepartmentId = d.Id
group by e.DepartmentId;
solution
# 创建一个临时表(内联视图),查询每个部门的最大薪资。之后在Employeee和Department的联合表中找到一名部门与薪资与
# 临时表中相符的记录。SELECT d.name AS Department, e.Name AS Employee, e.Salary AS Salary
FROMEmployee e,Department d,(SELECT DepartmentId, MAX(Salary) AS max_salary FROM Employee GROUP BY DepartmentId) AS temp
WHEREe.DepartmentId = d.IdAND e.Salary = temp.max_salaryAND e.DepartmentId = temp.DepartmentId;
solution -2
# 使用子查询+in操作(可以匹配多个列)
SELECT d.name Department, e.name Employee, e.Salary Salary
FROMEmployee e,Department d
WHEREe.DepartmentId = d.IdAND (e.DepartmentId , e.Salary) IN (SELECT DepartmentId, MAX(Salary) FROM Employee GROUP BY DepartmentId);
12. 第二高的薪水
编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary)。
如果不存在第二高的薪水,那么查询应返回 null。
schema
drop table if exists Employee;
Create table Employee (Id int, Salary int);
insert into Employee (Id, Salary) values ('1', '100');
insert into Employee (Id, Salary) values ('2', '200');
insert into Employee (Id, Salary) values ('3', '300');
solution distinct + limit(从0开始的offset, 行数(-1表示末尾)) + 子查询
# 额外嵌套一个select以实现没有符合记录时返回null
SELECT (SELECT DISTINCTSalaryFROMEmployeeORDER BY Salary DESCLIMIT 1 , 1) AS SecondHighestSalary;
13. 编写一个 SQL 查询,获取 Employee 表中第 n 高的薪水(Salary)。
如果不存在第 n 高的薪水,那么查询应返回 null。
solution 自定义函数
/**
MySQL默认结束符是;,但函数声明中含有:,所以使用delimiter将
分隔符临时改成其它符号,例如$$;
**/
delimiter $$
create function getNthHighestSalary (N int) returns int
beginset N = N - 1;return (select (select distinct Salary from Employee order by Salary DESC limit N, 1));
end
$$
delimiter ;select getNthHighestSalary(1);
14. 分数排名
编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。
请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。
schema
/**
decimal:数字型,不存在精度损失
decimal(18, 9) 表示总共18位,小数部分9位。
**/
DROP TABLE IF EXISTS Scores;
CREATE TABLE Scores ( Id INT, Score DECIMAL ( 3, 2 ) );
INSERT INTO Scores ( Id, Score )
VALUES( 1, 3.5 ),( 2, 3.65 ),( 3, 4.0 ),( 4, 3.85 ),( 5, 4.0 ),( 6, 3.65 );
solution
select Score, temp.Rank from
(select s1.Id id, count(distinct s2.Score) Rank
from Scores s1 Inner join Scores s2 on s1.Score <= s2.Score group by
s1.Id) as temp, Scores
order by Rank DEsc;
15. 补充-1 分段统计 贝壳面试题
有person表,字段有ID、Age,统计每个年龄段的人数,10-20,20-30等等。
shcema
drop table person_beike;
create table if not exists person_beike (id int primary key auto_increment, age int1);
truncate table person_beike;
insert into person_beike (age) values
(1),
(12),
(21),
(31),
(41),
(51),
(52),
(90);
solution-1 利用union合并多个查询
SELECT “xxx” col可在结果集中添加col列,其列内容为xxx。
select "0-10" type, count(*) count from person_beike where age <= 10
union
select "10-20" type, count(*) count from person_beike where age > 10 and age <= 20;
LeetCode SQL 刷题相关推荐
- Leetcode SQL 刷题 Mysql【2】
[11]595. 大的国家 select name,population,area from World where area > 3000000 or population > 2500 ...
- 牛客网SQL刷题笔记(MySQL)
牛客网SQL刷题笔记(MySQL) 此博客集合LeetCode.牛客网常见的题型及其解法,侵删 目录 牛客网SQL刷题笔记(MySQL) 类型1:查找排名第几的数据 SQL2 查找入职员工时间排名倒数 ...
- 【Leetcode】 刷题之路1(python)
leetcode 刷题之路1(python) 看到有大佬总结了一些相关题目,想着先刷一类. 1.两数之和 15.三数之和 16.最接近的三数之和 11.盛最多的水 18.四数之和 454.四数相加II ...
- leetcode每日刷题计划-简单篇day8
leetcode每日刷题计划-简单篇day8 今天是纠结要不要新买手机的一天QAQ想了想还是算了吧,等自己赚钱买,加油 Num 70 爬楼梯 Climbing Stairs class Solutio ...
- 「数据库」sql刷题(No.11)
喜欢就 关注 我们吧! 简介: Hello 各位 ,我是公号「八点半技术站」的创作者 - Bruce.D (姓氏:豆). 感谢微信给予的个人认证,专注于PHP.Go.数据库技术领域知识经验分享. 技 ...
- LeetCode代码刷题(17~24)
目录 17. 电话号码的字母组合 18. 四数之和 19. 删除链表的倒数第 N 个结点 20. 有效的括号 21. 合并两个有序链表 22. 括号生成 23. 合并K个升序链表 24. 两两交换链表 ...
- leetcode分类刷题笔记
leetcode分类刷题笔记--基于python3 写在前面 1.做题如果实在想不出时间复杂度比较优的解法,可以先写出暴力解法,尝试在其基础上优化 2.排序.双指针.二分等--经常可以优化时间复杂度 ...
- SQL刷题记录(一)
SQL刷题记录(一) 答主刚开始自学SQL,本专栏记录的是答主在牛客上刷题的过程.疑惑和部分思路都会写在习题下方. 题目来源:牛客网刷题网址 本文内容:T195-T225 T195. select * ...
- 【SQL刷题】DAY16----SQL高级联结专项练习
博主昵称:跳楼梯企鹅 博主主页面链接:主页传送门 博主专栏页面连接:网络安全专栏传送么门 创作初心:本博客的初心为与技术朋友们相互交流,每个人的技术都存在短板,博主也是一样,虚心求教,希望各位技术友给 ...
最新文章
- 程序员工资为什么高?
- R语言警告:Cannot compute exact p-value with ties的处理方法
- Android最佳的开源库(四)
- Linux内核中的进程组及会话
- Scala模式匹配中的变量
- java源程序加密解决方案(基于Classloader解密)
- 微电子科学与工程要学计算机吗,微电子科学与工程专业就业前景如何 有前途吗...
- HDU 4722	Good Numbers 2013年四川省赛题
- 《C++编程——数据结构与程序设计方法》程序范例:影碟店(源代码)
- android sdk引入 微信分享_Android 微信SDK分享功能中的最全过程步骤分析
- java--Date时间
- Java基础002 Java9开发环境搭建(Win10平台)
- 去掉内容中的所有全部html标签。
- 做片子留着备用 超级游戏影视配乐音效库36套合集
- 如何使用gdb调试java虚拟机_Eclispe+qemu+gdb调试linux Kernel
- MarkDown 分割线
- MOOC创新创业学第十二章单元测试题及答案
- Google DFP广告管理系统简介:开始与您的网站进行广告集成
- qduoj 分辣条2
- java 葫芦娃.rmvb,课内资源 - 基于JAVA的葫芦娃 — 最终之战
热门文章
- 快速入手springboot
- 彻底理解 模拟频率、数字频率、模拟角频率
- 是到了更换项目管理工具的时候了吗? (转)
- HTML5调用摄像头录制视频
- GPUImageMovieWrite录制MP4视频出现can't write frame解决方法
- 『.NET Tools』在.Net Core中实现汉字转拼音
- 【绝对干货】2021年哔哩哔哩Java高级面试题及答案,完整版开放下载
- uni - app 的 pages.json 文件页面配置与全局配置
- java设置阴影边框_CSS边框阴影效果:box-shadow属性的使用解释
- B站上诉A站抢注商标被驳回,承担案件受理费100元