MySQL50-7 - вопросы 21-25
В этой статье представлены темы 21–25. Основные вопросы, связанные с этим:
- Сумма групповой статистики, процент
- Как использовать SQL для сортировки
- использование
- союз сращивания
5 тем:
- запрос отличаетсяучительучили по-другомукурс среднийОтображение от высокого к низкому
- Запросить информацию о студентах, занявших со 2-го по 3-е место во всех курсах и оценках курса.
- Подсчитайте количество людей по каждому предмету и классу: номер курса, название курса, [100-85], [85-70], [70-60], [0-60] и процент
- Запрос средней оценки и рейтинга учеников
- Запросить записи трех лучших результатов по каждому предмету
тема 21
требования темы
запрос отличаетсяучительучили по-другомукурс среднийОтображение от высокого к низкому
Процесс анализа
Используемые таблицы в основном
Учитель: Учитель
Курс: Курс, как основная таблица
Оценка: Оценка
Его можно получить, соединив 3 стола
Реализация SQL
Начните с выяснения того, какие курсы преподает каждый учитель:
select
c.c_name
,t.t_name
from Course c
left join Teacher t
on c.t_id = t.t_id;
Комбинируя вышеуказанные результаты слист оценоксоедините их:
select
c.c_name
,t.t_name
,round(avg(s.s_score),2) score -- 课程分组后再求均值
from Course c -- 主表,通过两次连接
left join Teacher t
on c.t_id = t.t_id
left join Score s
on c.c_id = s.c_id
group by c.c_id -- 课程分组
order by 3 desc; -- 降序
тема 22
требования темы
Запросить информацию о студентах, занявших со 2-го по 3-е место во всех курсах и оценках курса.
Процесс анализа
Оценка: Оценка
Информация о студенте: Студент
Мы соединили 2-й и 3-й по каждому предмету, а затем вынули информацию о студенте.
Реализация SQL
собственный метод
1. Расписание курса и лист оценок подключены для отображения всей информации о курсе и оценках.
select
s.s_id
,s.c_id
,s.s_score
,c.c_name
from Score s
join Course c
on s.c_id = c.c_id
2. Узнайте все баллы по языку
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;
3. Находим 2-го и 3-го учеников китайского
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;
4. Получите баллы по китайскому языку, математике и английскому языку одновременно и сдайтеunion
соединение
-- 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)
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))
5. Подключите приведенную выше таблицу результатов с информацией о студентах.
По крайней мере, это сбылось ?
-- 最终脚本
-- !!!!真的需要好好优化下
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)
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
Тот же метод, что и вопрос 25
1. Взяв в качестве примера китайский язык, сначала находим 3 верхние оценки (включая одинаковые оценки)
-- 语文
select
a.s_id
,a.c_id
,a.s_score -- 3、此时a表的成绩就是我们找的
from Score a
join Score b
on a.c_id = b.c_id
and a.s_score <= b.s_score -- 1、判断a的分数小于等于b的分数,要带上等号
and a.c_id="01"
group by 1,2
having count(b.s_id) <= 3 -- 2、b中的个数至少有3个,应对分数相同的情形
order by 3 desc
limit 1,2
-- 语文
select
a.s_id
,a.c_id
,a.s_score -- 3、此时a表的成绩就是我们找的
from Score a
join Score b
on a.c_id = b.c_id
and a.s_score <= b.s_score -- 1、判断a的分数小于等于b的分数,要带上等号
and a.c_id="01"
group by 1,2
having count(b.s_id) <= 3 -- 2、b中的个数至少有3个,应对分数相同的情形
order by 3 desc
limit 1,2; -- 取得第2、3名
Получите 2-й и 3-й классы через аналогичные операции по математике и английскому языку, а потом можно делать сплайсинг.
тема 23
требования темы
Подсчитайте количество людей по каждому предмету и классу: номер курса, название курса, [100-85], [85-70], [70-60], [0-60] и процент
Процесс анализа
Курс: Курс
Оценка: Оценка
Оператор case используется для суждения, оператор count используется для статистики, а оператор sum используется для суммирования.
Реализация SQL
собственный метод
1. Как отображать каждую оценку в группах: ABCD представляет соответствующую оценку
select
c_id
,s_score
,case when s_score >= 85 and s_score<= 100 then 'A' -- 大小关系必须分两次写,一次写的话MySQL无法识别
when 70 <= s_score and s_score < 85 then 'B'
when 60 <= s_score and s_score < 70 then 'C'
when 0 <= s_score and s_score < 60 then 'D'
else '其他' end as 'category'
from Score s;
2. Свяжите две таблицы для отображения данных
-- 1、查看全部课程和成绩信息
select
s.c_id
,c.c_name
,s.s_score
,case when s.s_score >= 85 and s.s_score<= 100 then 'A' -- 大小关系必须分两次写,一次写的话MySQL无法识别
when 70 <= s.s_score and s.s_score < 85 then 'B'
when 60 <= s.s_score and s.s_score < 70 then 'C'
when 0 <= s.s_score and s.s_score < 60 then 'D'
else '其他' end as 'category'
from Score s
join Course c
on s.c_id = c.c_id;
3. Полный код
select
s.c_id 编号
,c.c_name 科目
,sum(case when s.s_score >= 85 and s.s_score<= 100 then 1 else 0 end) "[85,100]人数"
,round(100 * (sum(case when s.s_score >= 85 and s.s_score<= 100 then 1 else 0 end) / sum(case when s.s_score then 1 else 0 end)), 2) as '[85,100]百分比'
,sum(case when s.s_score >= 70 and s.s_score<= 85 then 1 else 0 end) "[70,85]人数"
,round(100 * (sum(case when s.s_score >= 70 and s.s_score<= 85 then 1 else 0 end) / sum(case when s.s_score then 1 else 0 end)), 2) as '[70,85]百分比'
,sum(case when s.s_score >= 60 and s.s_score<= 70 then 1 else 0 end) "[60,70]人数"
,round(100 * (sum(case when s.s_score >= 60 and s.s_score<= 70 then 1 else 0 end) / sum(case when s.s_score then 1 else 0 end)), 2) as '[60,70]百分比'
,sum(case when s.s_score >= 0 and s.s_score<= 60 then 1 else 0 end) "[0,60]人数"
,round(100 * (sum(case when s.s_score >= 0 and s.s_score<= 60 then 1 else 0 end) / sum(case when s.s_score then 1 else 0 end)), 2) as '[0,60]百分比'
from Score s
left join Course c
on s.c_id = c.c_id
group by s.c_id, c.c_name
Эталонный метод
1. Сначала подсчитайте количество и долю каждого этапа
select
c_id
,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) '占比'
from Score
group by c_id; -- 分课程统计总数和占比
-- 方式2
select
c_id
,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(case when s_score then 1 else 0 end)), 2) '占比' -- 不同count(*)
from Score
group by c_id;
Обратите внимание на сравнение:
2. Выясним 4 случая одновременно
select
c_id
,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
group by c_id; -- 分课程统计总数和占比
3. Соедините имена предметов
-- 整体和自己的方法是类似的
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; -- 分课程统计总数和占比
тема 24
требования темы
Запрос средней оценки и рейтинга учеников
Процесс анализа
Студент: Студент
Оценка: Оценка
Среднее: функция среднего
Ранжирование: Решено путем сортировки
Реализация SQL
собственный метод
1. Сначала найдите средний балл каждого человека
-- 自己的方法
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
2. Сортируем результаты выше
! ! !В MySQL5 нет функции ранжирования, вам нужно реализовать функцию сортировки самостоятельно
-- MYSQL5.7中没有rank函数,所以通过自连接实现
select
t1.s_id
,t1.s_name
,t1.avg_score
,(select count(distinct t2.avg_score)
from (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)t2 -- 临时表t2也是上面的结果
where t2.avg_score >= t1.avg_score
) rank
from (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)t1 -- 临时表t1就是上面的结果
order by t1.avg_score desc;
Эталонный метод
select
a.s_id -- 学号
,@i:=@i+1 as '不保留空缺排名' -- 直接i的自加
,@k:=(case when @avg_score=a.avg_s then @k else @i end) as '保留空缺排名'
,@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
s.s_name -- 姓名
,s.s_score -- 成绩
,(select count(distinct t2.s_score)
from Score t2
where t2.s_score >= t1.s_score) rank -- 在t2分数大的情况下,统计t2的去重个数
from Score t1
order by t1.s_score desc; -- 分数降序排列
Пример для иллюстрации этого скрипта:
Имя | достижение |
---|---|
Чжан Сан | 89 |
Ли Си | 90 |
Ван Ву | 78 |
Сяо Мин | 98 |
немного красный | 60 |
- Когда t1.s_score=89, t2.s_score >= t1.s_score98, 90 и 89, в это время количество count(различных t2.s_score) равно 3
- Когда t1.s_score=90, t2.s_score >= t1.s_score имеет98 и 90, в это время количество count(различных t2.s_score) равно 2
- Когда t1.s_score=78, t2.s_score >= t1.s_score имеет98, 90, 89 и 78, в это время количество count(различных t2.s_score) равно 4
- Когда t1.s_score=98, только те, которые удовлетворяют t2.s_score >= t1.s_score98, в это время количество count(различных t2.s_score) равно 1
- Когда t1.s_score=60, t2.s_score >= t1.s_scoreЕсть 89, 90, 78, 98, 60, в это время количество count(различных t2.s_score) равно 5
Выполнив описанные выше шаги, мы обнаружили, что:Число, соответствующее каждой оценке в t1, является ее рангом.
тема 25
требования темы
Запросить записи трех лучших результатов по каждому предмету
Процесс анализа
Этот вопрос и вопрос 22 относятся к одному и тому же типу: чтобы найти оценки указанных рейтингов по каждому предмету, используется следующая таблица:Score
Реализация SQL
собственный метод
1. Сначала мы находим топ-3 языка
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 -- 降序之后取出前3条记录
limit 3;
2. Таким же методом можем найти первые 3 записи по математике и английскому языку, а потом соединить их объединением, которое нужно оптимизировать ?
-- 自己的脚本
(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 -- 降序之后取出前3条记录
limit 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 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 3)
Эталонный метод
Через самоподключение таблицы Score значение в таблице а меньше значения в таблице б, после сортировки берем первые 3
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 -- 表b中的成绩大
group by 1,2,3
having count(b.s_id) = 3
order by 2, 3 desc;
мы проходим语文
Этот предмет, чтобы понять приведенный выше код:Топ-3: 80, 80, 76
-- 语文
select
a.s_id
,a.c_id
,a.s_score -- 3、此时a表的成绩就是我们找的
from Score a
join Score b
on a.c_id = b.c_id
and a.s_score <= b.s_score -- 1、判断a的分数小于等于b的分数,要带上等号
and a.c_id="01"
group by 1,2
having count(b.s_id) <= 3 -- 2、b中的个数至少有3个,应对分数相同的情形
order by 3 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 -- 1、判断a的分数小于等于b的分数,要带上等号
group by 1,2,3
having count(b.s_id) <= 3 -- 2、b中的个数至少有3个,应对分数相同的情形
order by 2, 3 desc; -- 课程(2)的升序,成绩()3的降序