安装准备

mysql安装:终于把mysql装回来了_mysql-9.3.0-winx64-CSDN博客

navicat安装:

通过网盘分享的文件:Navicat Premium 17.0.8 (x64破解压缩包).zip
链接: https://pan.baidu.com/s/176_aELzZNy1M5s_Lb35_hA?pwd=wkqd 提取码: wkqd

解压安装包

点install然后等待安装完成,找到Crack文件夹下的winmm.dll,复制粘贴到Navicat Premium的安装位置即可激活(可以在桌面找到图标右击,打开文件所在在位置)

哈哈哈哈,完了,我的exe是在英文版官网下的,说要在中文版官网才会有语言可以改,算了,我习惯习惯把,就当练英语了。用网盘的应该没问题,因为那是后来找的网盘

navicat连接mysql

选择mysql

然后双击那个小海豚,就会变绿说明连接成功。

练习

题目来源:(33 封私信) 图解SQL面试题:经典50题 - 知乎https://zhuanlan.zhihu.com/p/38354000?utm_campaign=shareopn&utm_medium=social&utm_oi=965340081422360576&utm_psn=1577015079509356544&utm_source=wechat_session已知四张表:

学生表:student(学号,学生姓名,出生年月,性别)

成绩表:score(学号,课程号,成绩)

课程表:course(课程号,课程名称,教师号)

教师表:teacher(教师号,教师姓名)

关系图(大佬那来的):

1.创建数据库

双击刚刚创建的数据库

2.创建四张表

1)创建学生表(student)


2)创建成绩表(score)

3)创建课程表(course)

4)教师表(teacher)

3.插入数据

1)插入学生信息(注意中英文符号)

insert into student(学号,姓名,出生日期,性别)
VALUES('0001','猴子','1989-01-01','男');

insert into student(学号,姓名,出生日期,性别) 
values('0002' , '猴子' , '1990-12-21' , '女');

insert into student(学号,姓名,出生日期,性别) 
values('0003' , '马云' , '1991-12-21' , '男');

insert into student(学号,姓名,出生日期,性别) 
values('0004' , '王思聪' , '1990-05-20' , '男');

点击保存,命名:student查询(随你)

双击查看

2)插入成绩信息

insert into score(学号,课程号,成绩) 
values('0001' , '0001' , 80);

insert into score(学号,课程号,成绩) 
values('0001' , '0002' , 90);

insert into score(学号,课程号,成绩) 
values('0001' , '0003' , 99);

insert into score(学号,课程号,成绩) 
values('0002' , '0002' , 60);

insert into score(学号,课程号,成绩) 
values('0002' , '0003' , 80);

insert into score(学号,课程号,成绩) 
values('0003' , '0001' , 80);

insert into score(学号,课程号,成绩) 
values('0003' , '0002' , 80);

insert into score(学号,课程号,成绩) 
values('0003' , '0003' , 80);

3)插入课程信息

insert into course(课程号,课程名称,教师号)
values('0001' , '语文' , '0002');

insert into course(课程号,课程名称,教师号)
values('0002' , '数学' , '0001');

insert into course(课程号,课程名称,教师号)
values('0003' , '英语' , '0003');

4)插入教师信息


insert into teacher(教师号,教师姓名) 
values('0001' , '孟扎扎');

insert into teacher(教师号,教师姓名) 
values('0002' , '马化腾');

insert into teacher(教师号,教师姓名) 
values('0003' , null);

insert into teacher(教师号,教师姓名) 
values('0004' , '');

4.查询语句

1)查询姓猴的

SELECT *FROM student where 姓名 like '猴%';

2)查询名字最后是猴的

SELECT *FROM student where 姓名 like '%猴';

3)查询名字带猴的

SELECT *FROM student where 姓名 like '%猴%';

4)查询名字带猴的个数

SELECT count(学号) as 带猴的个数  FROM student   where 姓名 like '%猴%';

5.汇总分析

1)查询课程编号为“0002”的总成绩

SELECT sum(成绩)as 总成绩   FROM score where   学号='0002';

2)查询选了课程的学生人数(去重)

SELECT count(DISTINCT(学号)) FROM score;

分组

3)查询各科成绩最高和最低的分

SELECT 课程号, max(成绩)as 最高成绩,min(成绩) as 最低成绩 FROM score GROUP BY 课程号;

4)查询每门课程被选修的学生数

SELECT 课程号,count(学号) as 选课人数 FROM score GROUP BY 课程号;

5)查询男生、女生人数

SELECT 性别,count(*) as 选课人数 FROM student GROUP BY 性别;

分组结果+条件

6).查询平均成绩大于60分学生的学号和平均成绩

SELECT 学号,avg(成绩) as 平均成绩 from score GROUP  BY 学号 HAVING avg(成绩);

7).查询至少选修两门课程的学生学号

select 学号, count(课程号) as 选修课程数目 from score group by 学号 having count(课程号)>=2;

8).查询同名同姓学生名单并统计同名人数

select 姓名,count(*)as 同名人数 from student GROUP BY 姓名 having count(*)>1;

9).查询不及格的课程并按课程号从大到小排列

select 课程号 from score  where 成绩<60 order by 课程号 desc;

10).查询每门课程的平均成绩,结果按平均成绩升序排序,平均成绩相同时,按课程号降序排列

SELECT 课程号,avg(成绩)as 平均成绩 from score GROUP BY 课程号 order BY avg(成绩) asc,课程号 DESC;

11).检索课程编号为“0002”且分数小于80的学生学号,结果按按分数降序排列

select 学号 from score where 课程号='0002' and 成绩 <80 order by 成绩 desc;

12).统计每门课程的学生选修人数(超过2人的课程才统计),要求输出课程号和选修人数,查询结果按人数降序排序,若人数相同,按课程号升序排序

SELECT 课程号,count(学号) as 学生选修人数 FROM score GROUP BY 课程号 having count(学号)>1 ORDER BY '选修人数' desc,课程号 asc; 

13).查询两门以上不及格课程的同学的学号及其平均成绩

select 学号, avg(成绩) as 平均成绩
from score
where 成绩 <60
group by 学号
having count(课程号)>2;

查询结构排序,分组的指定条件

14)查询学生的总成绩并进行排名

SELECT 学号,sum(成绩)as 总成绩 FROM score GROUP BY 学号 ORDER BY sum(成绩) DESC; 

15)查询平均成绩大于60分的学生的学号和平均成绩

SELECT 学号,avg(成绩)as 平均成绩 from score GROUP BY 学号 having avg(成绩)>60; 

6.复杂查询

1)查询所有课程成绩小于60分学生的学号、姓名(子查询)

SELECT 学号,姓名 from student 
where 学号 in (SELECT 学号 from score where 成绩<60);

2)查询没有学全所有课的学生的学号、姓名

思路:没有学全所有课,也就是该学生选修的课程数 < 总的课程数
SELECT 学号,姓名 
from student 
where 学号 in(
select 学号 
from score 
GROUP BY 学号 
having count(课程号)<(SELECT count(课程号)from course));

3)查询出只选修了两门课程的全部学生的学号和姓名

select 学号,姓名 from student where 学号 in (SELECT 学号 from score GROUP BY 学号 having count(课程号)=2);

4)1990年出生的学生名单

SELECT * FROM student where 出生日期 like '1990%';(这个是我自己写的)

select 学号,姓名  from student  where year(出生日期)=1990; (大佬的)

查询各科成绩前两名的记录

这题我本来想这么写的:SELECT 课程号 ,TOP2 with ties 成绩 from score GROUP BY 课程号 ORDER BY 成绩 DESC;(但好像是mysql不支持),所以应该是

SELECT 课程号, 成绩
FROM (
    SELECT 课程号, 成绩,
           DENSE_RANK() OVER (PARTITION BY 课程号 ORDER BY 成绩 DESC) AS rnk
    FROM score
) ranked_scores
WHERE rnk <= 2;

多看,不太熟练

5)查询各学生的年龄(精确到月份)

select 学号 ,timestampdiff(month ,出生日期 ,now())/12 
from student ;

6)查询本月过生日的学生

SELECT * FROM student where month(出生日期)=month(CURRENT_DATE);

7.多表查询

1)查询所有学生的学号、姓名、选课数、总成绩

SELECT a.学号,a.姓名,count(b.课程号) as 课程数,sum(b.成绩) as 总成绩 
FROM student a join score b on a.学号=b.学号 
GROUP BY 学号; 

2)查询平均成绩大于85的所有学生的学号、姓名和平均成绩

SELECT a.学号,a.姓名,avg(b.成绩)as 平均成绩 
FROM student a join score b 
on a.学号=b.学号
GROUP BY 学号 
HAVING avg(成绩)>85; 

3)查询学生的选课情况:学号,姓名,课程号,课程名称

SELECT a.学号, a.姓名,b.课程号,c.课程名称 
from student a 
join score b on a.学号=b.学号  
join course c on b.课程号=c.课程号;

4)查询出每门课程的及格人数和不及格人数

select 课程号,
sum(case when 成绩>=60 then 1 
     else 0 
    end) as 及格人数,
sum(case when 成绩 <  60 then 1 
     else 0 
    end) as 不及格人数
from score
group by 课程号;

5)使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,分别统计:各分数段人数,课程号和课程名称

 SELECT a.课程号,b.课程名称,
sum(case when a.成绩<60 then 1 else 0 end) as '60以下',
sum(case when a.成绩>=60 and  a.成绩<70 then 1 else 0 end) as '70-60',
sum(case when a.成绩>=70 and  a.成绩<85 then 1 else 0 end) as '85-70',
sum(case when a.成绩>=85 and  a.成绩<100 then 1 else 0 end) as '100-85'
FROM score a join course b 
on a.课程号=b.课程号
GROUP BY a.课程号,b.课程名;

6)查询课程编号为0003且课程成绩在80分以上的学生的学号和姓名|

SELECT a.学号,a.姓名 
from student a join score b 
on a.学号=b.学号
where b.课程号='0003' and 成绩>80
GROUP BY b.学号;

7)行列转换

从这样

转换成这样

SELECT 学号,
MAX(CASE WHEN 课程号 = '0001' THEN 成绩 ELSE 0 END) AS 课程号0001,
MAX(CASE WHEN 课程号 = '0002' THEN 成绩 ELSE 0 END) AS 课程号0002,
MAX(CASE WHEN 课程号 = '0003' THEN 成绩 ELSE 0 END) AS 课程号0003
FROM score
GROUP BY 学号;

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

SELECT b.*,a.`成绩` from score a join student b 
on a.`学号`=b.`学号`
where a.`课程号`=0001 and a.`成绩`<60
ORDER BY a.`成绩` DESC

9)查询不同老师所教不同课程平均分从高到低显示

SELECT c.`教师姓名`, avg(a.成绩) as 平均分
FROM score a
JOIN course b ON a.`课程号`=b.`课程号`
JOIN teacher c ON b.`教师号`=c.`教师号`
GROUP BY c.`教师姓名`
ORDER BY avg(a.`成绩`) DESC;

10)询课程名称为"数学",且分数低于60的学生姓名和分数

SELECT a.姓名,b.成绩
from student a 
join score b 
on a.`学号`=b.`学号`
join course c 
on b.`课程号`=c.`课程号`
where c.`课程名称`='数学' and b.成绩<60;

11)查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩

SELECT b.学号,a.姓名,avg(b.成绩) as平均成绩
from student a join score b 
on a.学号=b.学号
where b.`成绩`<60
GROUP BY b.学号
HAVING count(b.课程号)>1;

12)查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩

SELECT distinct a.学号,a.课程号,a.成绩
FROM score a join score b 
where a.成绩=b.成绩 and a.课程号!=b.课程号 and a.学号!=b.学号;

13)查询课程编号为“0001”的课程比“0002”的课程成绩高的所有学生的学号

SELECT a.学号
FROM score a
JOIN score b ON a.学号 = b.学号
WHERE a.课程号 = '0001' 
AND b.课程号 = '0002'
AND a.成绩 > b.成绩;

×14)查询学过“孟扎扎”老师所教的所有课的同学的学号、姓名

SELECT s.学号, s.姓名
FROM student s
JOIN score sc ON s.学号 = sc.学号
JOIN course c ON sc.课程号 = c.课程号
JOIN teacher t ON c.教师号 = t.教师号
WHERE t.教师姓名 = '孟扎扎'
GROUP BY s.学号, s.姓名
HAVING COUNT(DISTINCT sc.课程号) = (
    SELECT COUNT(*) 
    FROM course 
    WHERE 教师号 = (SELECT 教师号 FROM teacher WHERE 教师姓名 = '孟扎扎')
);

15)查询没学过"孟扎扎"老师讲授的任一门课程的学生姓名(与上题类似,"没学过"用not in来实现)

SELECT s.学号, s.姓名
FROM student s
JOIN score sc ON s.学号 = sc.学号
JOIN course c ON sc.课程号 = c.课程号
JOIN teacher t ON c.教师号 = t.教师号
WHERE t.教师姓名 not in (select t.`教师姓名` from teacher where t.`教师姓名`='孟扎扎')
GROUP BY s.学号, s.姓名;

16)查询选修“孟扎扎”老师所授课程的学生中成绩最高的学生姓名及其成绩(与上题类似,用成绩排名,用 limit 1得出最高一个)

SELECT a.姓名,b.成绩
from student a join score b on a.学号=b.学号 
join course c on b.课程号=c.课程号 
join teacher d on c.教师号=d.教师号
where d.教师姓名='孟扎扎'
ORDER BY b.成绩 desc limit 1;

17)查询至少有一门课与学号为“0001”的学生所学课程相同的学生的学号和姓名

SELECT b.学号,a.姓名 
from student a join score b on a.学号=b.学号 
where b.课程号 in 
(SELECT DISTINCT b.课程号 from score where b.学号='0001') 
and b.学号!='0001';

18)按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩

select a.学号,avg(a.成绩),
max(case when b.课程名称  = '数学' then a.成绩 else null end ) as '数学',
max(case when b.课程名称  = '语文' then a.成绩 else null end ) as '语文',
max(case when b.课程名称  = '英语' then a.成绩 else null end ) as '英语'
from score a join course b on a.课程号=b.课程号
GROUP BY a.学号
ORDER BY avg(a.成绩) desc ;

8.SQL高级功能:窗口函数

ROW_NUMBER()窗口函数,常与 OVER()子句一起使用。

用法示例:

SELECT id, name, ROW_NUMBER() OVER (ORDER BY id) AS row_num FROM your_table;

这里的 ROW_NUMBER()就是为每一行按 id排序后分配一个从 1 开始递增的编号。

类似的窗口函数还有:

RANK():排名,允许并列,后续排名会跳过。

DENSE_RANK():排名,允许并列,但后续排名不跳过。

NTILE(n):将数据分成 n 个桶,为每行分配一个桶号。

1)查询学生平均成绩及其名次

SELECT 学号,avg(成绩)as 平均成绩,
ROW_NUMBER() OVER (ORDER BY avg(成绩) desc) AS 排名
from score 
GROUP BY 学号;

2)按各科成绩进行排序,并显示排名

SELECT 课程号,学号,成绩,
ROW_NUMBER() over (PARTITION by 课程号  ORDER BY 成绩 desc) as 排名
FROM score ;

3)查询每门功成绩最好的前两名学生姓名

SELECT 
  b.课程号,a.学号,a.姓名,b.成绩,b.排名
from 
  student a 
join (
  SELECT 课程号,学号,成绩,
  ROW_NUMBER() OVER (PARTITION BY 课程号 ORDER BY 成绩 DESC) AS 排名 
  FROM score
) as b on a.学号=b.学号
where b.排名<3;

4)查询所有课程的成绩第2名到第3名的学生信息及该课程成绩(与上一题相似)

SELECT 
  b.课程号,a.学号,a.姓名,b.成绩,b.排名
from 
  student a 
join (
  SELECT 课程号,学号,成绩,
  ROW_NUMBER() OVER (PARTITION BY 课程号 ORDER BY 成绩 DESC) AS 排名 
  FROM score
) as b on a.学号=b.学号
where b.排名 in (2,3);

×5)查询各科成绩前三名的记录(不考虑成绩并列情况)(与上一题相似)

SELECT 
  b.课程号,a.学号,a.姓名,b.成绩,b.排名
from 
  student a 
join (
  SELECT 课程号,学号,成绩,
  ROW_NUMBER() OVER (PARTITION BY 课程号 ORDER BY 成绩 DESC) AS 排名 
  FROM score
) as b on a.学号=b.学号
where b.排名 in (1,2,3);


终于全部练完了,坚持就是胜利!!!

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐