sql训练
2023年8月13日大约 21 分钟
面试题
相关表请参照文档
课程1比课程2分数高的
- 学生表Student 和Score表
- 查询"01"课程比"02"课程成绩高的学生的信息及课程分数
select
a.*,
b.s_score 01_score,
c.s_score 02_score
from
Student a
inner join Score b on a.s_id = b.s_id
and b.c_id = '01'
inner join Score c on a.s_id = c.s_id
and c.c_id = '02'
WHERE
b.s_score > c.s_score;

平均成绩大于60分
#求平均成绩,需要分组后利用avg函数求平均值,然后通过having 对分组后的数据进行过滤
select
a.*,
COUNT(b.c_id),
AVG(b.s_score) as avg_score
from
Student a
inner join Score b on a.s_id = b.s_id
group by
a.s_id
having
avg_score >= 60
order by
avg_score
desc

所有课程的总成绩
- 查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩
-- [分析]学生编号、学生姓名在表student中;选课数可通过在表score中通过group by 学生编号后利用count(c_id)算出;所有课程的总成绩则用sum可以算出。
-- 因为要用到表student和表score,故需要对表进行联结。
select
a.s_id,
a.s_name,
Count(b.c_id),
Sum(b.s_score)
from
Student a
inner join Score b on a.s_id = b.s_id
group by
a.s_id

查询"李"姓老师的数量
-- [分析] 这里用到知识点字符串模糊查询,如:where 姓名 like '猴%' 即可查到猴什么什么。
-- 关于字符串模糊查询的知识点可查看我的另一篇文章《SQL学习笔记——汇总分析》
select
count(t_name) as number
from
Teacher
where
t_name like '李%';

学过"张三"老师课的同学
-- [分析] 老师的信息在表teacher中,可通过teacher.t_id与表course联结,
-- 再通过course.c_id与表score联结,
-- 再再通过score.s_id与表student联结,查找出上过张三老师课的同学的信息。
SELECT
stu.s_id,
stu.s_name,
stu.s_birth,
stu.s_sex
FROM
Teacher tea
inner join Course cou on tea.t_id = cou.t_id
inner join Score sco on sco.c_id = cou.c_id
inner join Student stu on stu.s_id = sco.s_id
WHERE
tea.t_name = '张三';

学过01、02两门课的同学
- x学过编号为"01"并且也学过编号为"02"的课程的同学的信息

# 方法一 内连接+子查询
SELECT
stu.*
FROM
Student stu
WHERE
stu.s_id in (
SELECT
a.s_id
FROM
Student a
inner join Score b on a.s_id = b.s_id
and b.c_id = '01'
inner join Score c on a.s_id = c.s_id
and c.c_id = '02'
)
# 方法二 内连接
SELECT
a.*
FROM
Student a
inner join Score b on a.s_id = b.s_id
and b.c_id = '01'
inner join Score c on a.s_id = c.s_id
and c.c_id = '02'
学过01没学过02
- 学过编号为"01"但是没有学过编号为"02"的课程的同学的信息
SELECT
*
FROM
Student
WHERE
s_id in (
SELECT
a.s_id
FROM
Student a
inner join Score b on a.s_id = b.s_id
and b.c_id = '01'
)
and s_id not in (
SELECT
a.s_id
FROM Student a
inner join Score b on a.s_id = b.s_id
and b.c_id = '02'
)

没有学全所有课程的同学
- 查询没有学全所有课程的同学的信息
---> 方法一,利用条件子查询,s_id不在学了所有课程同学集合里的学生就是需要得结果
SELECT
*
FROM
Student
where
s_id not in (
SELECT
s_id
FROM
Score
group by
s_id
having
COUNT(c_id) = (
SELECT
COUNT(c_id)
FROM
Course
)
)
---> 左连接 分组后过滤
select
a.*
from
Student a
left join Score b on a.s_id = b.s_id
group by
a.s_id
having
COUNT(b.c_id) < (
select
COUNT(c_name)
from
Course
)

没学过张三课程的同学
- 查询没学过"张三"老师讲授的任一门课程的学生姓名
select
s_name
from
Student
where
s_id not in (
select
s_id
from
Score
where
c_id not in (
select
c_id
from
Course
where
t_id != (
select
t_id
from
Teacher
where
t_name = '张三'
)
)
)

两门课不及格的学生
- 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
SELECT
a.*,
avg(b.s_score)
FROM
Student a
INNER JOIN Score b on a.s_id = b.s_id
and b.s_score < 60
group by
s_id
having
COUNT(b.s_score) >= 2

"01"课程分数小于60
- 检索"01"课程分数小于60,按分数降序排列的学生信息

select
*
from
Student a
inner join Score b on a.s_id = b.s_id
where
b.s_score < 60
order by
b.s_score
desc

按照平均成绩排序
重要
按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩(重要!)
# 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩(重要!)
select
a.s_id,
a.s_name,
(
select
s_score
from
Score
where
c_id = "01"
and s_id = a.s_id
) as '语文',
(
select
s_score
from
Score
where
c_id = "02"
and s_id = a.s_id
) as '数学',
(
select
s_score
from
Score
where
c_id = "03"
and s_id = a.s_id
) as '英语',
round(avg(s_score)) as "平均分"
from
Student a
left join Score b on a.s_id = b.s_id
group by
a.s_id
order by
平均分
desc
---> 方法二
select
a.s_name,
a.s_sex,
a.s_birth,
SUM(case when b.c_id = '01' then b.s_score else 0 end) as score01,
SUM(case when b.c_id = '02' then b.s_score else 0 end) as score02,
SUM(case when b.c_id = '03' then b.s_score else 0 end) as score03,
SUM(b.s_score) as scoreSum,
round(avg(b.s_score)) as scoreAvg
from
Student a
inner join Score b on a.s_id = b.s_id
group by
a.s_id
order by
scoreAvg
desc
各科成绩最高分、最低分和平均分
重要
查询各科成绩最高分、最低分和平均分
- 以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,
- 优秀率--及格为>=60,
- 中等为:70-80,
- 优良为:80-90,
- 优秀为:>=90(重要!)

注
考察mysql的函数用法,需要加强常用函数的使用
Mysql SUM( case when 条件 then .... else.... end )
-- 查询各科成绩的最高分、最低分、和平均分
select
b.c_id,
b.c_name,
MAX(a.s_score) as '最高分',
MIN(a.s_score) as '最低分',
AVG(a.s_score) as '平均分',
ROUND(
100.00 * SUM(CASE WHEN a.s_score >= 60 then 1 else 0 END) / SUM(CASE WHEN a.s_score then 1 else 0 end),
2
) as 及格率,
ROUND(
100.00 * SUM(case when a.s_score BETWEEN 70 AND 80 then 1 else 0 end) / SUM(case when a.s_score then 1 else 0 end),
2
) as 中等率,
ROUND(
100.00 * SUM(case when a.s_score BETWEEN 80 AND 90 then 1 else 0 end) / SUM(case when a.s_score then 1 else 0 end),
2
) as 优良率,
ROUND(
100.00 * SUM(CASE WHEN a.s_score >= 90 then 1 else 0 END) / SUM(CASE WHEN a.s_score then 1 else 0 end),
2
) as 优良率
from
Score a
right join Course b on a.c_id = b.c_id
group by
b.c_id
order by
最高分
desc
学生的总成绩并进行排名
.png)
select
a.s_id,
a.s_name,
SUM(b.s_score)
from
Student a
inner join Score b on a.s_id = b.s_id
group by
a.s_id
不同老师不同课程的平均分
- 查询不同老师所教不同课程平均分从高到低显示

# 查询不同老师所教不同课程平均分从高到低显示
SELECT
t.*,
AVG(s.s_score) as 平均分
FROM
Teacher t
INNER JOIN Course c on t.t_id=c.t_id
INNER JOIN Score s on s.c_id = c.c_id
GROUP BY (c.c_id)
ORDER BY
平均分
DESC
查询第二名到第三名的成绩
- 查询所有课程的总成绩第2名到第3名的学生信息以及总课程成绩
注
limit的语法:limit [offset, ], rows
参数说明:
- offset:指定第一个返回行的偏移量(即从哪一行开始返回, 从offset+1开始算起)
- rows: 返回的具体行数
常见的四种用法:
-- -- 有两个参数 select * from user limit 2, 5 -- 从第三行开始,取5行数据
-- 只有一个参数 select * from user limit 5; -- 从第0行开始取5条数据
-- 分页 select * from user (curpage -1)*pageSize, pageSize; -- 查询第一页,每页设置三条数据 ,将curpage = 1, pageSize = 3带入 select * from user 0, 3 -- (1-1)*3, 3 -- 查村第三页,每页设置三条数据 select * from user 6, 3
-- limit + offset -- Limit第一个参数就是offset,但为了兼容postgresql数据库,mysql中也可以采用以下方法来使用,此时limit只负责取数量,offset负责偏移量 select * from user limit 6 offset 2;
select
a.*,
SUM(b.s_score) as total
from
Student a
inner join Score b on a.s_id = b.s_id
group by
a.s_id
order by
total
desc
limit 1, 2

各科成绩的前三名
重要
查询各科成绩前三名的记录(重要!!!!!)
UNION函数的使用
(
select
a.*,
b.*
from
Score a
inner join Student b on a.s_id = b.s_id
and c_id = '01'
order by
s_score
desc
limit
3
)
union all
(
select
a.*,
b.*
from
Score a
inner join Student b on a.s_id = b.s_id
and c_id = '02'
order by
s_score
desc
limit
3
)
union all
(
select
a.*,
b.*
from
Score a
inner join Student b on a.s_id = b.s_id
and c_id = '03'
order by
s_score
desc
limit
3
)
每门课被选修的学生数
select
a.c_name,
COUNT(b.s_id) as 选修人数
from
Course a
inner join Score b on a.c_id = b.c_id
group by
a.c_id
order by
选修人数

只有两门课的学生
select
a.*
from
Student a
inner join Score b on a.s_id = b.s_id
group by
a.s_id
having COUNT(a.s_id) =2;
查询男生、女生人数
# 方法1:
select
s_sex,
count(s_sex) as 人数
from
Student
GROUP BY
s_sex
# 方法2:
(
select
s_sex,
count(s_sex) as 人数
from
Student
where
s_sex = '男'
)
union
(
select
s_sex,
count(s_sex) as 人数
from
Student
where
s_sex = '女'
)

名字中含有"风"的学生
SELECT * FROM Student WHERE s_name LIKE'%风%'
同名同姓的学生
- 查询同名同性学生名单,并统计同名人数(重要!!!!!)
select
a.s_name,
count(*) as 人数
from
Student a,
Student b
where
a.s_name = b.s_name
group by
a.s_name
having
人数 >= 2
查询1990年出生的学生
-- [分析] 字符串模糊查询
SELECT
*
FROM
Student
WHERE
s_birth like "1990%"
课程成绩平均排列
- 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列
select
a.*,
AVG(b.s_score)
from
Course a
inner join Score b
group by
a.c_id
order by
a.c_id asc

平均成绩大于等于85的学生
select
a.*,
AVG(b.s_score)
from
Student a
inner join Score b on a.s_id = b.s_id
group by
b.s_id
having
AVG(b.s_score) > 85

课程为数学且分数低于60
- 查询课程名称为"数学",且分数低于60的学生姓名和分数
select
a.*,
b.s_score
from
Student a
inner join Score b on a.s_id = b.s_id
inner join Course c on c.c_id=b.c_id and c.c_name='数学'

任意一门成绩在70分以上
- 查询任何一门课程成绩在70分以上的姓名、课程名称和分数;
select
a.*,
c.c_name,
b.s_score
from
Student a
inner join Score b on a.s_id = b.s_id and b.s_score>70
inner join Course c on c.c_id=b.c_id

查询所有不及格学生
- 查询所有不及格学生的姓名、课程名称和分数
select
a.*,
c.c_name
from
Student a
inner join Score b on a.s_id = b.s_id
and b.s_score < 60
inner join Course c on b.c_id = c.c_id

课程为01成绩80分以上
- 查询课程编号为01且课程成绩在80分以上的学生的学号和姓名
select
a.s_id,
a.s_name
from
Student as a
inner join Score as b on a.s_id = b.s_id
and b.s_id >= 80
and b.c_id = '01'
求每门课程的学生人数
select
a.c_name,
count(b.s_id)
from
Course as a
inner join Score as b on a.c_id = b.c_id
group by
a.c_id
张三老师课程成绩最高的学生
- 查询选修"张三"老师所授课程的学生中,成绩最高的学生信息及其成绩
select
*
from
Student a
inner join Score b on a.s_id = b.s_id
inner join Course c on b.c_id = c.c_id
inner join Teacher d on d.t_id = c.c_id
and d.t_name = '张三'
order by
b.s_score
desc
limit
1 offset 0
不同课程成绩相同的学生
注意
- 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩 (重要!!!!)
select
*
from
Student a
inner join Score b on a.s_id = b.s_id
inner join Score c on a.s_id = b.s_id
where
b.s_score = c.s_score and b.c_id != c.c_id

每门功课成绩最好的前两名
(select c_id,s_score from Score where c_id = '01' order by s_score desc limit 2)
UNION
(select c_id,s_score from Score where c_id = '02' order by s_score desc limit 2)
UNION
(select c_id,s_score from Score where c_id = '03' order by s_score desc limit 2)
# 思路: 自己join自己,条件为a.c_id = b.c_id and a.s_score < b.s_score
# 其实就是列出同一门课程内所有分数比较情况
# 然后通过a.c_id 和b.s_id联合分组,可以确定同一门课程这个学生比其他学生究竟高\低多少
# 如果特定的a.c_id,a.s_id组合出现在这个表里的次数少于2,那就意味着这个组合(课程+学号+分数)在这门课程是排名#前二的
# 所以下面这个计算中having count 部分其实count()或者任意其他列都可以,这里制定了一个列只是因为比count()运行速度上更快
select
a.s_id,
a.c_id,
a.s_score
from
Score a
left join Score b on a.c_id = b.c_id
and a.s_score < b.s_score
group by
a.c_id,
a.s_id
having
COUNT(a.c_id) < 2
order by
a.c_id

选修学生超过5人
- 统计每门课程的学生选修人数(超过5人的课程才统计)。
- 要求输出
课程号和选修人数
,查询结果按人数降序排列,若人数相同,按课程号升序排列
select
c_id,
COUNT(s_id)
from
Score
group by
c_id
having
COUNT(s_id) > 5
order by
COUNT(s_id) desc,
c_id asc
选修全部课程的学生
- 查询选修了全部课程的学生信息
select
a.s_id,
b.s_name
from
Score a
inner join Student b on a.s_id=b.s_id
group by
s_id
having
COUNT(c_id) >= (
select
COUNT(c_id)
from
Course
)

下周过生日的学生
select
*
from
Student
where
WEEK(DATE_FORMAT(NOW(), '%Y%m%d')) + 1 = WEEK(s_birth)
每门成绩大于80的学生
select
a.*,
b.*
from
Score a
inner join Student b on a.s_id=b.s_id
group by
a.s_id,a.c_id
having a.s_score > 80

组合两个表
表: Person +-------------+---------+ | 列名 | 类型 | +-------------+---------+ | PersonId | int | | FirstName | varchar | | LastName | varchar | +-------------+---------+ personId 是该表的主键列。 该表包含一些人的 ID 和他们的姓和名的信息。 表: Address +-------------+---------+ | 列名 | 类型 | +-------------+---------+ | AddressId | int | | PersonId | int | | City | varchar | | State | varchar | +-------------+---------+ addressId 是该表的主键列。 该表的每一行都包含一个 ID = PersonId 的人的城市和州的信息。 编写一个SQL查询来报告 Person 表中每个人的姓、名、城市和州。如果 personId 的地址不在 Address 表中,则报告为空 null 。 以 任意顺序 返回结果表。 查询结果格式如下所示。 示例 1: 输入: Person表: +----------+----------+-----------+ | personId | lastName | firstName | +----------+----------+-----------+ | 1 | Wang | Allen | | 2 | Alice | Bob | +----------+----------+-----------+ Address表: +-----------+----------+---------------+------------+ | addressId | personId | city | state | +-----------+----------+---------------+------------+ | 1 | 2 | New York City | New York | | 2 | 3 | Leetcode | California | +-----------+----------+---------------+------------+ 输出: +-----------+----------+---------------+----------+ | firstName | lastName | city | state | +-----------+----------+---------------+----------+ | Allen | Wang | Null | Null | | Bob | Alice | New York City | New York | +-----------+----------+---------------+----------+ 解释: 地址表中没有 personId = 1 的地址,所以它们的城市和州返回 null。 addressId = 1 包含了 personId = 2 的地址信息。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/combine-two-tables 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
select a.* from Person as a
left join Address as b on b.personId=a.personId

第二高的薪水
Employee 表: +-------------+------+ | Column Name | Type | +-------------+------+ | id | int | | salary | int | +-------------+------+ 在 SQL 中,id 是这个表的主键。 表的每一行包含员工的工资信息。 查询并返回 Employee 表中第二高的薪水 。如果不存在第二高的薪水,查询应该返回 null(Pandas 则返回 None) 。 查询结果如下例所示。 示例 1: 输入: Employee 表: +----+--------+ | id | salary | +----+--------+ | 1 | 100 | | 2 | 200 | | 3 | 300 | +----+--------+ 输出: +---------------------+ | SecondHighestSalary | +---------------------+ | 200 | +---------------------+ 示例 2: 输入: Employee 表: +----+--------+ | id | salary | +----+--------+ | 1 | 100 | +----+--------+ 输出: +---------------------+ | SecondHighestSalary | +---------------------+ | null | +---------------------+ 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/second-highest-salary 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
# 这种方式会在没有第二高的薪水时报错
SELECT salary as SecondHighestSalary FROM Employee order by salary desc limit 1 offset 1;
# 将结果作为零时表就不会报错
select
(
select
salary
from
Employee a
order by
salary
limit
1 offset 1
) as SecondHighestSalary;
#另一种解决 'NULL' 问题的方式是使用下面的 #IFNULL 函数。 如果不为 NULL,IFNULL 函数会返#回第一个参数,否则返回第二个参数。
#这为我们提供了正确的解决方案,即一行包含 NULL #(如果没有这样的第 2 高薪资),而不仅仅是一个空#表。
select
IFNULL(
(
select
salary
from
Employee
order by
salary
limit
1 offset 1
), NULL
) as SecondHighestSalary
MySQL子句的执行顺序
FROM 子句:指定从中检索数据的表。 WHERE 子句:根据指定的条件筛选行。 GROUP BY 子句:根据指定的列或表达式对行进行分组。 HAVING 子句:根据条件筛选分组的行。 SELECT 子句:选择将在结果集中返回的列或表达式。 ORDER BY 子句:根据指定的列或表达式对结果集进行排序。 LIMIT/OFFSET 子句:限制结果集中返回的行数。 where>group by>having>order by
第N高的薪水
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
DECLARE M INT; // 定义变量
SET M = N-1;
RETURN(
SELECT DISTINCT salary FROM Employee ORDER BY salary DESC LIMIT M,1
);
END
分数排名
表: Scores +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | score | decimal | +-------------+---------+ 在 SQL 中,id 是该表的主键。 该表的每一行都包含了一场比赛的分数。Score 是一个有两位小数点的浮点值。 查询并对分数进行排序。排名按以下规则计算: 分数应按从高到低排列。 如果两个分数相等,那么两个分数的排名应该相同。 在排名相同的分数后,排名数应该是下一个连续的整数。换句话说,排名之间不应该有空缺的数字。 按 score 降序返回结果表。 查询结果格式如下所示。 示例 1: 输入: Scores 表: +----+-------+ | id | score | +----+-------+ | 1 | 3.50 | | 2 | 3.65 | | 3 | 4.00 | | 4 | 3.85 | | 5 | 4.00 | | 6 | 3.65 | +----+-------+ 输出: +-------+------+ | score | rank | +-------+------+ | 4.00 | 1 | | 4.00 | 1 | | 3.85 | 2 | | 3.65 | 3 | | 3.65 | 3 | | 3.50 | 4 | +-------+------+ 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/rank-scores 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
select
a.score,
(
select
count(distinct(score))
from
Scores b
where
b.score >= a.score
) as 'rank'
from
Scores a
order by
a.score
desc
# 窗口函数
select
s.score,
DENSE_RANK() OVER(
ORDER BY
s.score
desc
) AS 'rank'
from
Scores s
连续出现的数字
表:Logs +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | num | varchar | +-------------+---------+ 在 SQL 中,id 是该表的主键。 id 是一个自增列。 找出所有至少连续出现三次的数字。 返回的结果表中的数据可以按 任意顺序 排列。 结果格式如下面的例子所示: 示例 1: 输入: Logs 表: +----+-----+ | id | num | +----+-----+ | 1 | 1 | | 2 | 1 | | 3 | 1 | | 4 | 2 | | 5 | 1 | | 6 | 2 | | 7 | 2 | +----+-----+ 输出: Result 表: +-----------------+ | ConsecutiveNums | +-----------------+ | 1 | +-----------------+ 解释:1 是唯一连续出现至少三次的数字。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/consecutive-numbers 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
# Write your MySQL query statement below
select
distinct(l1.num) as ConsecutiveNums
from
Logs l1,
Logs l2,
Logs l3
where
l1.id + 1 = l2.id
and l1.id + 2 = l3.id
and l1.num = l2.num
and l2.num = l3.num

超过经理收入的员工
表:Employee +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | name | varchar | | salary | int | | managerId | int | +-------------+---------+ Id是该表的主键。 该表的每一行都表示雇员的ID、姓名、工资和经理的ID。 编写一个SQL查询来查找收入比经理高的员工。 以 任意顺序 返回结果表。 查询结果格式如下所示。 示例 1: 输入: Employee 表: +----+-------+--------+-----------+ | id | name | salary | managerId | +----+-------+--------+-----------+ | 1 | Joe | 70000 | 3 | | 2 | Henry | 80000 | 4 | | 3 | Sam | 60000 | Null | | 4 | Max | 90000 | Null | +----+-------+--------+-----------+ 输出: +----------+ | Employee | +----------+ | Joe | +----------+ 解释: Joe 是唯一挣得比经理多的雇员。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/employees-earning-more-than-their-managers 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
# Write your MySQL query statement below
select
b.name as Employee
from
Employee a,
Employee b
where
a.id = b.ManagerId
and a.salary < b.salary

查找重复的电子邮箱
表: Person +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | email | varchar | +-------------+---------+ id 是该表的主键列。 此表的每一行都包含一封电子邮件。电子邮件不包含大写字母。 编写一个 SQL 查询来报告所有重复的电子邮件。 请注意,可以保证电子邮件字段不为 NULL。 以 任意顺序 返回结果表。 查询结果格式如下例。 示例 1: 输入: Person 表: +----+---------+ | id | email | +----+---------+ | 1 | a@b.com | | 2 | c@d.com | | 3 | a@b.com | +----+---------+ 输出: +---------+ | Email | +---------+ | a@b.com | +---------+ 解释: a@b.com 出现了两次。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/duplicate-emails 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
# Write your MySQL query statement below
# 解法一 group + having
SELECT email as Email FROM Person GROUP BY email having count(email) >= 2;
# 使用临时表
SELECT email FROM
(
SELECT email, count(email) as num FROM Person group by email
) as statistic where num >1;
从不订购的用户
Customers 表: +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | name | varchar | +-------------+---------+ 在 SQL 中,id 是该表的主键。 该表的每一行都表示客户的 ID 和名称。 Orders 表: +-------------+------+ | Column Name | Type | +-------------+------+ | id | int | | customerId | int | +-------------+------+ 在 SQL 中,id 是该表的主键。 customerId 是 Customers 表中 ID 的外键( Pandas 中的连接键)。 该表的每一行都表示订单的 ID 和订购该订单的客户的 ID。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/customers-who-never-order 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
# 解法一,使用select子查询
SELECT Customers.name as `Customers`
From Customers
where id not in (select customerId From Orders);
# 解法二, left join
select name as `Customers`
FROM Customers
LEFT JOIN orders on Customers.id = orders.customerId where orders.customerId is null;
部门工资最高的员工
表: Employee +--------------+---------+ | 列名 | 类型 | +--------------+---------+ | id | int | | name | varchar | | salary | int | | departmentId | int | +--------------+---------+ 在 SQL 中,id是此表的主键。 departmentId 是 Department 表中 id 的外键(在 Pandas 中称为 join key)。 此表的每一行都表示员工的 id、姓名和工资。它还包含他们所在部门的 id。 表: Department +-------------+---------+ | 列名 | 类型 | +-------------+---------+ | id | int | | name | varchar | +-------------+---------+ 在 SQL 中,id 是此表的主键列。 此表的每一行都表示一个部门的 id 及其名称。 查找出每个部门中薪资最高的员工。 按 任意顺序 返回结果表。 查询结果格式如下例所示。 示例 1: 输入: Employee 表: +----+-------+--------+--------------+ | id | name | salary | departmentId | +----+-------+--------+--------------+ | 1 | Joe | 70000 | 1 | | 2 | Jim | 90000 | 1 | | 3 | Henry | 80000 | 2 | | 4 | Sam | 60000 | 2 | | 5 | Max | 90000 | 1 | +----+-------+--------+--------------+ Department 表: +----+-------+ | id | name | +----+-------+ | 1 | IT | | 2 | Sales | +----+-------+ 输出: +------------+----------+--------+ | Department | Employee | Salary | +------------+----------+--------+ | IT | Jim | 90000 | | Sales | Henry | 80000 | | IT | Max | 90000 | +------------+----------+--------+ 解释:Max 和 Jim 在 IT 部门的工资都是最高的,Henry 在销售部的工资最高。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/department-highest-salary 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
select
Department.name as `Department`,
Employee.name as `Employee`,
Salary
FROM
Department,
Employee
WHERE
Employee.DepartmentId = Department.Id
and
(
Employee.DepartmentId, Salary
)
in
(
select DepartmentId, MAX(Salary
)
FROM Employee Group by DepartmentId
)
部门工资前三高的员工
表: Employee +--------------+---------+ | Column Name | Type | +--------------+---------+ | id | int | | name | varchar | | salary | int | | departmentId | int | +--------------+---------+ Id是该表的主键列。 departmentId是Department表中ID的外键。 该表的每一行都表示员工的ID、姓名和工资。它还包含了他们部门的ID。 表: Department +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | name | varchar | +-------------+---------+ Id是该表的主键列。 该表的每一行表示部门ID和部门名。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/department-top-three-salaries 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处
# Write your MySQL query statement below
# 获取每个部门前三
select d.name as Department , e1.name as Employee, e1.salary FROM
Employee e1
join Department d on e1.departmentId=d.id
where 3> (
SELECT count(distinct(e2.salary))
FROM Employee e2
where e2.salary>e1.salary
and e1.departmentId=e2.departmentId
order by salary desc
);
删除重复的电子邮箱
表: `Person` +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | email | varchar | +-------------+---------+ id 是该表的主键列(具有唯一值的列)。 该表的每一行包含一封电子邮件。电子邮件将不包含大写字母。 编写解决方案 **删除** 所有重复的电子邮件,只保留一个具有最小 `id` 的唯一电子邮件。 (对于 SQL 用户,请注意你应该编写一个 `DELETE` 语句而不是 `SELECT` 语句。) (对于 Pandas 用户,请注意你应该直接修改 `Person` 表。) 运行脚本后,显示的答案是 `Person` 表。驱动程序将首先编译并运行您的代码片段,然后再显示 `Person` 表。`Person` 表的最终顺序 **无关紧要** 。 返回结果格式如下示例所示。 **示例 1:** 输入: Person 表: +----+------------------+ | id | email | +----+------------------+ | 1 | john@example.com | | 2 | bob@example.com | | 3 | john@example.com | +----+------------------+ 输出: +----+------------------+ | id | email | +----+------------------+ | 1 | john@example.com | | 2 | bob@example.com | +----+------------------+ 解释: john@example.com重复两次。我们保留最小的Id = 1。
delete p1 from
person as p1,
person as p2
where
where p1.email = p2.email and p1.id>p2.id
上升的温度
表:
Weather
+---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | recordDate | date | | temperature | int | +---------------+---------+ 在 SQL 中,id 是该表的主键。 该表包含特定日期的温度信息
找出与之前(昨天的)日期相比温度更高的所有日期的
id
。返回结果 无顺序要求 。
结果格式如下例子所示。
示例 1:
表: `Weather` ``` +---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | recordDate | date | | temperature | int | +---------------+---------+ 在 SQL 中,id 是该表的主键。 该表包含特定日期的温度信息 ``` 找出与之前(昨天的)日期相比温度更高的所有日期的 `id` 。 返回结果 **无顺序要求** 。 结果格式如下例子所示。 **示例 1:**
select w2.id
from
Weather w1
inner join
Weather W2
where
DATEDIFF(w2.recordDate, w1.recordDate) = 1
and
w2.temperature>w1.temperature