-- 1、学生表
-- Student(s_id,s_name,s_birth,s_sex) :学生编号、姓名、年月、性别
CREATE TABLE
IF NOT EXISTS `Student` (
`s_id` VARCHAR (20),
`s_name` VARCHAR (20) NOT NULL DEFAULT '',
`s_birth` VARCHAR (20) NOT NULL DEFAULT '',
`s_sex` VARCHAR (10) NOT NULL DEFAULT '',
PRIMARY KEY (`s_id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8;
-- 插入数据
INSERT INTO Student VALUES ('01', '赵雷', '1990-01-01', '男');
INSERT INTO Student VALUES ('02', '钱电', '1990-12-21', '男');
INSERT INTO Student VALUES ('03', '孙风', '1990-05-20', '男');
INSERT INTO Student VALUES ('04', '李云', '1990-08-06', '男');
INSERT INTO Student VALUES ('05', '周梅', '1991-12-01', '女');
INSERT INTO Student VALUES ('06', '吴兰', '1992-03-01', '女');
INSERT INTO Student VALUES ('07', '郑竹', '1989-07-01', '女');
INSERT INTO Student VALUES ('08', '王菊', '1990-01-20', '女');
-- 2、课程表
-- Course(c_id,c_name,t_id) :课程编号、 课程名称、 教师编号
CREATE TABLE
IF NOT EXISTS `Course` (
`c_id` VARCHAR (20),
`c_name` VARCHAR (20) NOT NULL DEFAULT '',
`t_id` VARCHAR (20) NOT NULL,
PRIMARY KEY (`c_id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8;
-- 插入数据
INSERT INTO Course VALUES ('01', '语文', '02');
INSERT INTO Course VALUES ('02', '数学', '01');
INSERT INTO Course VALUES ('03', '英语', '03');
-- 3、教师表
-- Teacher(t_id,t_name) :教师编号、教师姓名
CREATE TABLE
IF NOT EXISTS `Teacher` (
`t_id` VARCHAR (20),
`t_name` VARCHAR (20) NOT NULL DEFAULT '',
PRIMARY KEY (`t_id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8;
-- 插入数据
INSERT INTO Teacher VALUES ('01', '张三');
INSERT INTO Teacher VALUES ('02', '李四');
INSERT INTO Teacher VALUES ('03', '王五');
-- 4、成绩表
-- Score(s_id,c_id,s_score) :学生编号、课程编号、分数
CREATE TABLE
IF NOT EXISTS `Score` (
`s_id` VARCHAR (20),
`c_id` VARCHAR (20),
`s_score` INT (3),
PRIMARY KEY (`s_id`, `c_id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8;
-- 插入数据
INSERT INTO Score VALUES ('01', '01', 80);
INSERT INTO Score VALUES ('01', '02', 90);
INSERT INTO Score VALUES ('01', '03', 99);
INSERT INTO Score VALUES ('02', '01', 70);
INSERT INTO Score VALUES ('02', '02', 60);
INSERT INTO Score VALUES ('02', '03', 80);
INSERT INTO Score VALUES ('03', '01', 80);
INSERT INTO Score VALUES ('03', '02', 80);
INSERT INTO Score VALUES ('03', '03', 80);
INSERT INTO Score VALUES ('04', '01', 50);
INSERT INTO Score VALUES ('04', '02', 30);
INSERT INTO Score VALUES ('04', '03', 20);
INSERT INTO Score VALUES ('05', '01', 76);
INSERT INTO Score VALUES ('05', '02', 87);
INSERT INTO Score VALUES ('06', '01', 31);
INSERT INTO Score VALUES ('06', '03', 34);
INSERT INTO Score VALUES ('07', '02', 89);
INSERT INTO Score VALUES ('07', '03', 98);
-- 方法一:使用join连接
SELECT
a.*,
b.s_score,
c.s_score
FROM
Student a
JOIN Score b ON a.s_id = b.s_id
AND b.c_id = '01'
JOIN Score c ON a.s_id = c.s_id
AND c.c_id = '02'
WHERE
b.s_score > c.s_score;
-- 方法二:采用where语句
SELECT
a.*,
b.s_score,
c.s_score
FROM
Student a,
Score b,
Score c
WHERE
a.s_id = b.s_id
AND a.s_id = c.s_id
AND b.c_id = '01'
AND c.c_id = '02'
AND b.s_score > c.s_score;
SELECT
a.s_id,
a.s_name,
ROUND(AVG(b.s_score), 2) AS avg_score,
-- 求均值并保留2位小数
ROUND(SUM(b.s_score), 0) AS sum_score
-- 求和并保留0位小数
FROM
Student a
JOIN Score b ON a.s_id = b.s_id
GROUP BY
a.s_id
HAVING
avg_score >= 60
AND sum_score > 200
AND COUNT(b.s_score)=3;
SELECT
a.s_id,
a.s_name,
ROUND(AVG(b.s_score), 2) AS avg_score
FROM
Student a
LEFT JOIN Score b ON a.s_id = b.s_id
GROUP BY
a.s_id
HAVING
avg_score < 60;
SELECT
a.s_id,
a.s_name,
0 AS avg_score -- 将avg_score的值置为0
FROM
Student a
WHERE
a.s_id NOT IN (
-- 学生的学号不在给给定表的学号中
SELECT DISTINCT
s_id -- 查询出全部的学号
FROM
Score
);
-- 方法1:采用union函数进行合并
SELECT
a.s_id,
a.s_name,
ROUND(AVG(b.s_score), 2) AS avg_score
FROM
Student a
LEFT JOIN Score b ON a.s_id = b.s_id
GROUP BY
a.s_id
HAVING
avg_score < 60
UNION
SELECT
a.s_id,
a.s_name,
0 AS avg_score
FROM
Student a
WHERE
a.s_id NOT IN (
-- 学生的学号不在给给定表的学号中
SELECT DISTINCT
s_id -- 查询出全部的学号
FROM
Score
);
-- 方法2:采用ifnull函数
SELECT
S.s_id,
S.s_name,
ROUND(AVG(IFNULL(C.s_score, 0)), 2) AS avg_score -- ifnull 函数:第一个参数存在则取它本身,不存在取第二个值0
FROM
Student S
LEFT JOIN Score C ON S.s_id = C.s_id -- 一定要采用左连接
GROUP BY
s_id
HAVING
avg_score < 60;
-- 方法3:采用null函数
SELECT
a.s_id,
a.s_name,
ROUND(AVG(b.s_score), 2) AS avg_score
FROM
Student a
LEFT JOIN Score b ON a.s_id = b.s_id
GROUP BY
a.s_id
HAVING
avg_score < 60
OR avg_score IS NULL; -- 最后的NULL判断
SELECT
a.s_id,
a.s_name,
COUNT(b.c_id) AS count_course,
SUM(b.s_score) AS sum_socre
FROM
Student a
LEFT JOIN Score b ON a.s_id = b.s_id -- 采用left join,所以对于没有成绩的学生也可以筛选出来。
GROUP BY
a.s_id;
SELECT
COUNT(t_name)
FROM
Teacher
WHERE
t_name LIKE '李%'; -- 以李字开头的名字
-- 方法1:通过筛选出张三的id,并匹配相应的课程id,最后将学生的成绩与课程id进行匹配,最后筛选出符合条件的学生。
SELECT
a.*
FROM
Student a
JOIN Score b ON a.s_id = b.s_id
AND b.c_id =(
SELECT
c_id
FROM
Course
WHERE
t_id =(
SELECT
t_id
FROM
Teacher
WHERE
t_name = '张三'
));
-- 方法2:通过left join进行匹配
SELECT
a.*
FROM
Student a
JOIN Score b ON a.s_id = b.s_id
JOIN Course c ON b.c_id = c.c_id
JOIN Teacher d ON c.t_id = d.t_id
WHERE d.t_name='张三';
-- 方法1:通过筛选出张三的id,并匹配相应的课程id,然后将学生的成绩与张三老师课程id进行匹配,最后筛选不在次学生id范围内的学生信息。
SELECT
t3.*
FROM
Student t3
WHERE
t3.s_id NOT IN (
SELECT
t1.s_id
FROM
Score t1
JOIN Course t2 ON t1.c_id = t2.c_id
WHERE
t_id = (
SELECT
t_id
FROM
Teacher
WHERE
t_name = '张三'
)
);
-- 方法2:使用join
SELECT
a.*
FROM
Student a
WHERE
a.s_id NOT IN (
SELECT
s_id
FROM
Score a
JOIN Course b ON a.c_id = b.c_id
JOIN Teacher c ON b.t_id = c.t_id
WHERE
c.t_name = '张三'
);
-- 方法1:通过自连接实现
SELECT
a.*
FROM
Student a
WHERE
a.s_id IN (
SELECT
b.s_id
FROM
Score b
JOIN Score c ON b.s_id = c.s_id
WHERE
b.c_id = '01'
AND c.c_id = '02'
);
--方法2:通过where实现
SELECT
s1.*
FROM
Student s1,
Score s2,
Score s3
WHERE
s1.s_id = s2.s_id
AND s1.s_id = s3.s_id
AND s2.c_id = 01
AND s3.c_id = 02;
SELECT
s1.*
FROM
Student s1
WHERE
s1.s_id IN (
SELECT
s_id
FROM
Score
WHERE
c_id = '01'
) -- 修过01课程,要保留
AND s1.s_id NOT IN (
SELECT
s_id
FROM
Score
WHERE
c_id = '02'
);-- 哪些人修过02,需要排除
-- 方法1
select s.*
from Student s -- 学生表
left join Score s1 -- 成绩表
on s1.s_id = s.s_id
group by s.s_id -- 学号分组
having count(s1.c_id) < ( -- 分组后学生的课程数<3
select count(*) from Course -- 全部课程数=3
)
-- 方法2
select s.*
from Student s
where s_id not in (
select s_id
from Score s1
group by s_id
having count(*) = (select count(*) from Course)
);
SELECT
b.*
FROM
student b
LEFT JOIN score c ON b.s_id = c.s_id
WHERE
c.c_id IN ( SELECT a.c_id FROM score a WHERE a.s_id = '01' )
AND b.s_id != '01' --排除01学生自己
GROUP BY
b.s_id;
SELECT
b.*
FROM
student b
JOIN score c ON b.s_id = c.s_id
WHERE
b.s_id != '01'
GROUP BY
b.s_id
HAVING
COUNT( c.c_id )=(
SELECT
COUNT( c_id )
FROM
score
WHERE
s_id = '01')
group_concat([DISTINCT] 字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符'])
SELECT
b.s_id,
b.s_name,
b.s_sex,
GROUP_CONCAT( c.c_id ORDER BY c.c_id ) AS concat_course
FROM
student b
JOIN score c ON b.s_id = c.s_id
GROUP BY
b.s_id
HAVING
GROUP_CONCAT( c.c_id ORDER BY c.c_id )=(
SELECT
GROUP_CONCAT( c_id ORDER BY c_id )
FROM
score
WHERE
s_id = '01'
);
-- 方法1
SELECT
*
FROM
student
WHERE
s_id NOT IN (
SELECT DISTINCT
t1.s_id
FROM
score t1
JOIN course t2 ON t1.c_id = t2.c_id
WHERE
t2.t_id = (
SELECT
t_id
FROM
teacher
WHERE
t_name = '张三'
)
)
-- 方法2
SELECT
* -- 4、学号取反找到学生信息
FROM
Student
WHERE
s_id NOT IN (
SELECT DISTINCT
(s_id) -- 3、课程号找到对应的学号
FROM
Score
WHERE
c_id = (
SELECT
c_id -- 2、教师编号找到对应的课程号
FROM
Course
WHERE
t_id = (
SELECT
t_id -- 1、姓名找到教师编号
FROM
Teacher
WHERE
t_name = '张三'
)
)
);
SELECT
s.s_id,
s.s_name,
t.avg_score
FROM
Student s
JOIN (
SELECT
s_id,
ROUND(AVG(s_score)) avg_score --求均值再取整
FROM
Score
WHERE
s_score < 60
GROUP BY
s_id
HAVING
COUNT(s_score) >= 2
) t ON s.s_id = t.s_id
编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。
±—±-------+
| Id | Salary |
±—±-------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
±—±-------+
例如上述 Employee 表,SQL查询应该返回 200 作为第二高的薪水。如果不存在第二高的薪水,那么查询应返回 null。
±--------------------+
| SecondHighestSalary |
±--------------------+
| 200 |
±--------------------+
-- 第二高的薪水,除去最高薪水之后,在剩下的薪水中找最高的
select
max(Salary) as SecondHighestSalary -- 2、排除原数据中最高薪水之后,剩下的最大值就是第二高
from Employee
where Salary < (select max(Salary) from Employee); -- 1、这个select是找到原始数据中的最高薪水
缺点:当求第二高薪水的时候,只需要嵌套一层;如果求的是第3高,那么需要将第一高、第二高的同时排除,需要排除两次
-- 嵌套方法:找出第三高的薪水
select
max(Salary) as ThirdHighestSalary -- 3、确定第3高
from Employee
where Salary < (
select
max(Salary) as SecondHighestSalary -- 2、找到第二高
from Employee
where Salary < (select max(Salary) from Employee); -- 1、找到第一高
);
select
distinct Salary -- 去重
from Employee
order by Salary desc -- 薪水降序
limit 1 offset 1 -- 从第1行数据之后显示一行:除去最高的薪水之后再显示一行,也就是第二高的薪水
如果原数据中只存在一个最高值,也就说不存在第二高薪水的时候,需要显示为null,我们对上面的结果使用ifnull函数来实现
select ifnull((select distinct Salary -- 如果不存在则赋值为null
from Employee
order by Salary desc
limit 1 offset 1), null) as SecondHighestSalary
SELECT DISTINCT
s.s_score -- 分数去重
FROM
Score s
LEFT JOIN Course c ON s.c_id = c.c_id
WHERE
c.c_name = '语文' -- 指定科目
ORDER BY
s.s_score DESC -- 降序
LIMIT 1 OFFSET 1;-- limit和offset实现翻页功能
有一个 courses 表 ,有 student (学生) 和 class (课程)。请列出所有超过或等于5名学生的课。例如,表:
±--------±-----------+
| student | class |
±--------±-----------+
| A | Math |
| B | English |
| C | Math |
| D | Biology |
| E | Math |
| F | Computer |
| G | Math |
| H | Math |
| I | Math |
±--------±-----------+
最终的结果输出为:
±--------+
| class |
±--------+
| Math |
±--------+
在最下面有个提示:学生在每个课中不应被重复计算。即如果A同学重修了Math课程,则不应该被计算在内。
-- 方法1
select
class
from courses
group by class
having count(distinct student) >=5; -- distinct去重关键
-- 方法2
select
class
from(
select
distinct *
from courses) t -- 临时表
group by class
having count(class) >= 5;
本题中最大的陷阱就是有重修课程的同学,但是给出的数据中没有展现出来,所以上面的方法中都会出现去重的操作
Employee 表包含所有员工,他们的经理也属于员工。每个员工都有一个 Id,此外还有一列对应员工的经理的 Id。
±—±------±-------±----------+
| Id | Name | Salary | ManagerId |
±—±------±-------±----------+
| 1 | Joe | 70000 | 3 |
| 2 | Henry | 80000 | 4 |
| 3 | Sam | 60000 | NULL |
| 4 | Max | 90000 | NULL |
±—±------±-------±----------+
给定 Employee 表,编写一个 SQL 查询,该查询可以获取收入超过他们经理的员工的姓名。在上面的表格中,Joe 是唯一一个收入超过他的经理的员工。
±---------+
| Employee |
±---------+
| Joe |
±---------+
题目利用如下的图形解释:Joe是员工,工资是70000,经理是编号3,也就是Sam,但是Sam工资只有60000
-- 方法1:自连接
select
e1.Name as Employee
from Employee e1 -- 表的自连接
left join Employee e2
on e1.ManagerId = e2.Id -- 连接条件
where e1.Salary > e2.Salary
-- 方法2:where条件过滤
select
a.Name as Employee
from Employee as a,Employee as b -
where a.ManagerId = b.Id
and a.Salary > b.Salary;
SELECT
t1.s_id
,t1.s_name
,t1.s_birth
,t1.s_sex
,t2.s_score
FROM
student t1
JOIN score t2 ON t1.s_id = t2.s_id
WHERE
t2.c_id = 01
AND t2.s_score < 60
ORDER BY t2.s_score DESC;
-- 方法1
SELECT
t1.s_id,
t1.c_id,
t1.s_score,
t2.avg_score
FROM
score t1
JOIN ( -- 创建临时表,并进行连接
SELECT
s_id,
ROUND(AVG(s_score), 2) avg_score
FROM
score
GROUP BY
s_id
) t2 ON t1.s_id = t2.s_id
ORDER BY
4 DESC; -- 按照select中的第4列进行降序排列
-- 方法2:采用case when then end语句
SELECT
s.s_id,
MAX(CASE s.c_id WHEN '01' THEN s.s_score END) 语文,
MAX(CASE s.c_id WHEN '02' THEN s.s_score END) 数学,
MAX(CASE s.c_id WHEN '03' THEN s.s_score END) 英语,
ROUND(AVG(s.s_score), 2) avg_score
FROM
score s
GROUP BY
s.s_id
ORDER BY
5 DESC;
select
s.s_id
,max(case s.c_id when '01' then s.s_score end) 语文
,max(case s.c_id when '02' then s.s_score end) 数学
,max(case s.c_id when '03' then s.s_score end) 英语
,avg(s.s_score)
,b.s_name -- 没有出现在group by子句中,导致报错
from score s
join Student b
on s.s_id = b.s_id
group by s.s_id
order by 5 desc;
select
s.s_id
,max(case s.c_id when '01' then s.s_score end) 语文 -- 由于有些数据是空值,所以必须采用聚合函数,才能将真实值取出
,max(case s.c_id when '02' then s.s_score end) 数学
,max(case s.c_id when '03' then s.s_score end) 英语
,avg(s.s_score)
,b.s_name -- 没有出现在group by子句中,导致报错
from score s
join Student b
on s.s_id = b.s_id
group by s.s_id, b.s_name
order by 5 desc;
SELECT
t1.c_id,
t2.c_name
,MAX(t1.s_score) max_score
,MIN(t1.s_score) min_score
,ROUND(AVG(t1.s_score),2) avg_score
,ROUND(100*(SUM(CASE WHEN t1.s_score>=60 THEN 1 ELSE 0 END)/sum(CASE WHEN t1.s_score THEN 1 ELSE 0 END)),2) AS '及格率'
,ROUND(100*(SUM(CASE WHEN t1.s_score>=70 AND t1.s_score<=80 THEN 1 ELSE 0 END)/sum(CASE WHEN t1.s_score THEN 1 ELSE 0 END)),2) AS '中等率'
,ROUND(100*(SUM(CASE WHEN t1.s_score>=80 AND t1.s_score<=90 THEN 1 ELSE 0 END)/sum(CASE WHEN t1.s_score THEN 1 ELSE 0 END)),2) AS '优良率'
,ROUND(100*(SUM(CASE WHEN t1.s_score>=90 THEN 1 ELSE 0 END)/sum(CASE WHEN t1.s_score THEN 1 ELSE 0 END)),2) AS '优秀率'
FROM
score t1
JOIN course t2 ON t1.c_id = t2.c_id
GROUP BY
t1.c_id,
t2.c_name;
select * from (select
t1.c_id,
t1.s_score,
(select count(distinct t2.s_score)
from Score t2
where t2.s_score>=t1.s_score and t2.c_id='01') rank
from Score t1 where t1.c_id='01'
order by t1.s_score desc) t1
union
select * from (select
t1.c_id
,t1.s_score
,(select count(distinct t2.s_score)
from Score t2
where t2.s_score>=t1.s_score and t2.c_id='02') rank
from Score t1 where t1.c_id='02'
order by t1.s_score desc) t2
union
select * from (select
t1.c_id,
t1.s_score,
(select count(distinct t2.s_score) from Score t2 where t2.s_score>=t1.s_score and t2.c_id='03') rank
from Score t1 where t1.c_id='03'
order by t1.s_score desc) t3
select
t1.s_id ,t1.s_name, t1.score
,(select count(t2.score)
from(select s.s_id, s.s_name, sum(sc.s_score) score
from Student s
join Score sc
on s.s_id = sc.s_id
group by s.s_id
order by 3 desc)t2 -- t2和t1相同
where t2.score >= t1.score) as rank
from(
select s.s_id ,s.s_name ,sum(sc.s_score) score
from Student s
join Score sc
on s.s_id = sc.s_id
group by s.s_id
order by 3 desc)t1 -- t1
order by 3 desc;
-- 方法1
select
Email
from Person
group by Email
having count(Email) > 1; -- 过滤条件
-- 方法2
select
distinct (p1.Email) -- 去重统计邮箱
from Person p1
join Person p2 on p1.Email = p2.Email and p1.Id != p2.Id; -- 指定连接条件
select
name
,population
,area
from World
where area > 3000000
or population > 25000000;
-- 方法1
SELECT
Department.name AS 'Department',
Employee.name AS 'Employee',
Salary
FROM Employee
INNER JOIN Department ON Employee.DepartmentId = Department.Id
WHERE (Employee.DepartmentId , Salary) IN ( -- 两个字段同时使用
SELECT
DepartmentId, -- 部门分组找出部门号和薪水的最大值
MAX(Salary)
FROM Employee
GROUP BY DepartmentId
)
-- 方法2:
select
d.Name Department
,e.Name Employee
,e.Salary Salary
from Employee e , Department d
where e.DepartmentId = d.Id -- 在同一个部门中进行比计较
and e.Salary >= (select max(Salary) from Employee where DepartmentId=d.Id); -- 找出每个部门的最高值;如果大于等于这个最高值,肯定是最高的
SELECT S.NAME, S.EMPLOYEE, S.SALARY
FROM (SELECT
d.Name,
e.Name Employee,
e.Salary,
dense_rank() OVER(PARTITION BY e.DepartmentId ORDER BY e.Salary DESC) number -- 根据部门分区,薪水排序
FROM Employee e
LEFT JOIN Department d
ON e.DepartmentId = d.Id) S
WHERE S.number = 1 or S.number =3; -- 排名第一或者第三
SELECT
t2.t_name,
t2.c_name,
ROUND(AVG(t1.s_score), 2) AS avg_score
FROM
score t1
JOIN (
SELECT
a.t_name,
b.c_id,
b.c_name
FROM
teacher AS a,
course AS b
WHERE
a.t_id = b.t_id
) t2 ON t1.c_id = t2.c_id
GROUP BY t2.t_name, t2.c_name
ORDER BY ROUND(AVG(t1.s_score), 2) DESC;
SELECT
s.s_id,
s.s_name,
t.c_name,
t.s_score
FROM
Student s
JOIN (
-- union连接
(
SELECT
s.s_id,
s.s_score,
c.c_name
FROM
Score s
JOIN Course c ON s.c_id = c.c_id
WHERE
c.c_name = '语文'
ORDER BY
s.s_score DESC
LIMIT 1,2 -- 从第1行数据之后取2行,即取第2,3行数据
)
UNION
(
SELECT
s.s_id,
s.s_score,
c.c_name
FROM
Score s
JOIN Course c ON s.c_id = c.c_id
WHERE
c.c_name = '数学'
ORDER BY
s.s_score DESC
LIMIT 1, 2)
UNION
(
SELECT
s.s_id,
s.s_score,
c.c_name
FROM
Score s
JOIN Course c ON s.c_id = c.c_id
WHERE
c.c_name = '英语'
ORDER BY
s.s_score DESC
LIMIT 1, 2)
) t -- 临时表t
ON s.s_id = t.s_id
GROUP BY
t.c_name,
s.s_id,
s.s_name,
t.s_score
SELECT
s.c_id,
c.c_name,
sum( CASE WHEN s_score > 85 AND s_score <= 100 THEN 1 ELSE 0 END ) AS '85-100',
round( 100 * ( sum( CASE WHEN s_score > 85 AND s_score <= 100 THEN 1 ELSE 0 END ) / count(*)), 2 ) '[85,100]占比',
sum( CASE WHEN s_score > 70 AND s_score <= 85 THEN 1 ELSE 0 END ) AS '70-85',
round( 100 * ( sum( CASE WHEN s_score > 70 AND s_score <= 85 THEN 1 ELSE 0 END ) / count(*)), 2 ) '[70,85]占比',
sum( CASE WHEN s_score > 60 AND s_score <= 70 THEN 1 ELSE 0 END ) AS '60-70',
round( 100 * ( sum( CASE WHEN s_score > 60 AND s_score <= 70 THEN 1 ELSE 0 END ) / count(*)), 2 ) '[60,70]占比',
sum( CASE WHEN s_score >= 0 AND s_score <= 60 THEN 1 ELSE 0 END ) AS '0-60',
round( 100 * ( sum( CASE WHEN s_score > 0 AND s_score <= 60 THEN 1 ELSE 0 END ) / count(*)), 2 ) '[0,60]占比'
FROM
Score s
LEFT JOIN Course c ON s.c_id = c.c_id
GROUP BY
s.c_id,
c.c_name;-- 分课程统计总数和占比
select
a.s_id -- 学号
,@i:=@i+1 as '不保留空缺排名' -- 直接i的自加,顺序一直变大,声明变量需加@
,@k:=(case when @avg_score=a.avg_s then @k else @i+1 end) as '保留空缺排名' -- 只有在前后二次排序值不同时才会使顺序号加1
,@avg_score:=avg_s as '平均分' -- 表a中的值
from (select
s_id
,round(avg(s_score), 2) as avg_s
from Score
group by s_id
order by 2 desc)a -- 表a:平均成绩的排序和学号
,(select @avg_score:=0, @i:=0, @k:=0)b -- 表b:进行变量初始化,固定写法。
select
t1.c_id,
t1.s_score-- 成绩
,(select count(distinct t2.s_score) -- 排名从1开始
from Score t2
where t2.s_score >= t1.s_score) 排名 -- 在t2分数大的情况下,统计t2的去重个数
from Score t1
group by t1.c_id, t1.s_score
order by t1.s_score desc; -- 分数降序排列
select
a.s_id
,a.c_id
,a.s_score -- a表的成绩
from Score a
join Score b
on a.c_id = b.c_id
and a.s_score <= b.s_score -- 判断a的分数小于等于b的分数,要带上等号
group by 1,2,3
having count(b.s_id) <= 3 -- b中的个数至少有3个,应对分数相同的情形
order by 2, 3 desc; -- 课程(2)的升序,成绩(3)的降序
select
c.c_id
,c.c_name
,count(s.s_id)
from Course c
join Score s
on c.c_id = s.c_id
group by 1,2;
SELECT
t1.s_id
,t1.s_name
FROM
student t1
JOIN score t2 ON t1.s_id=t2.s_id
GROUP BY 1,2
HAVING COUNT(t2.s_score)=2;
select
s_sex
,count(s_sex) as `人数`
from Student
group by s_sex;
-- 模糊匹配:在两边都加上了%,考虑的是姓或者名字含有风
select * from Student where s_name like "%风%";
select
a.s_name
,a.s_sex
,count(*)
from Student a -- 同一个表的自连接
join Student b
on a.s_id != b.s_id -- 连接的时候不能是同一个人:学号保证,每个人的学号是唯一的,其他字段都可能重复
and a.s_sex = b.s_sex -- 性别相同
and a.s_name = b.s_name -- 名字相同
group by 1,2;
select
c.c_id
,c.c_name
,round(avg(sc.s_score),2) avg_score
from Score sc
join Course c
on sc.c_id = c.c_id
group by 1,2
order by 3 desc, c.c_id; -- 指定字段和排序方法
select
sc.s_id
,s.s_name
,round(avg(sc.s_score),2) avg_score
from Score sc
join Student s
on sc.s_id = s.s_id
group by sc.s_id,s.s_name
having avg_score >= 85;
select
s.s_id
,s.s_name
,sum(case c.c_name when '语文' then sc.s_score else 0 end) as '语文' -- 语文分数
,sum(case c.c_name when '数学' then sc.s_score else 0 end) as '数学'
,sum(case c.c_name when '英语' then sc.s_score else 0 end) as '英语'
,round(avg(sc.s_score),2) as '平均分' -- 每个人的平均分
,sum(sc.s_score) as '总分' -- 每个人的总分
from Student s
left join Score sc
on s.s_id = sc.s_id
left join Course c
on sc.c_id = c.c_id
group by s.s_id, s.s_name; -- 学号和姓名的分组
SELECT
t1.s_id,
t1.s_name,
t1.s_sex,
t1.s_birth,
t3.c_name,
t3.c_id,
MAX(t2.s_score)
FROM
student t1
JOIN score t2 ON t1.s_id = t2.s_id
JOIN course t3 ON t2.c_id = t3.c_id
JOIN teacher t4 ON t3.t_id = t4.t_id
WHERE
t4.t_name = '张三';
select
a.s_id
,a.c_id
,a.s_score
from Score a
join Score b
on a.c_id != b.c_id
and a.s_score = b.s_score
and a.s_id != b.s_id
group by 1,2,3;
SELECT
a.c_id,
a.s_id,
a.s_score
FROM
Score a
WHERE
( SELECT count( 1 ) -- count(1)类似count(*):统计表b中分数大的数量
FROM Score b WHERE b.c_id = a.c_id -- 课程相同
AND b.s_score >= a.s_score ) <= 2 -- 前2名
ORDER BY
a.c_id;
SELECT
c_id,
COUNT( s_id ) num
FROM
score
GROUP BY
c_id
HAVING
COUNT( s_id ) > 5
ORDER BY
COUNT( s_id ) DESC, c_id;
SELECT
s_id,
count(*) num
FROM
Score
GROUP BY
s_id
HAVING
count(*) >= 2;
select * -- 3、s_id对应的学生信息
from Student
where s_id in(select s_id -- 2、最大课程数对应的s_id
from Score
group by s_id
having count(*)=(select count(*) from Course) -- 1、全部课程数
)
select
s_name
,s_birth
,date_format(now(), '%Y') - date_format(s_birth, '%Y') - (case when date_format(now(), '%m%d') < date_format(s_birth, '%m%d') then 1 else 0 end) as age -- 当前日期大,说明已经过生了,年龄正常;反之说明今年还没有到年龄-1
from Student;
select * from Student where week(date_format(now(),'%Y%m%d')) = week(s_birth); -- 方式1
select * from student where yearweek(s_birth) = yearweek(date_format(now(),'%Y%m%d')); -- 方式2
select * from Student where week(date_format(now(),'%Y%m%d')) + 1= week(s_birth);
select * from Student
where mod(week(now()), 52) + 1 = week(s_birth);
当现在刚好是第52周,那么mod函数的结果是0,则说明出生的月份刚好是明年的第一周
select * from Student where month(date_format(now(), '%Y%m%d')) = month(s_birth);
select * from Student
where month(date_format(now(), '%Y%m%d')) + 1= month(s_birth);
select * from Student
where mod(month(now()),12) + 1 = month(s_birth);