sql vb xml 换行_SQL-持续更新语法&实战&面试题

a799c7aaf64dbc7d480d2da342c02920.png

写在前面:在互联网公司业务部门做分析师,一般会要求用SQL进行提数,这是必备的技能。这是一个我从入门到日常积累的帖子,内容循序渐进。第一篇是【入门】,写了我当时学习的步骤,建议控制在十天内搞定(PS:我当时基本就是上下班回家地铁上看的);第二篇是【刷题&面试题】,一定要保证每天都要刷,即使一道也行!保持手感!第三篇是【工作中遇到的语法记录】,会不定期更新,欢迎长期交流~


第一篇:入门-总耗时十天

关卡1-了解什么是数据库和SQL,并成功安装MYSQL-耗时一天

数据库(Database)是将大量数据保存起来,通过计算机加工而成的可以进行高效访问的数据集合。用来管理数据库的计算机系统称为数据库管理系统(DBMS)。DBMS能够实现多个用户同时安全简单地操作大量数据。DBMS的分类:层次数据库、关系数据库、面向对象数据库、XML数据库、键值存储系统。这里需要重点了解的是关系数据库(RDBMS),它是采用行和列组成的二维表来管理数据库,并使用专门的SQL(Structured Query Language,结构化查询语言)对数据进行操作。比较具有代表性的RDBMS有:

  • Oracle Database
  • SQL Server
  • DB2
  • PostgreSQL
  • MySQL

RDBMS最常见的系统结构就是客户端/服务器类型,简而言之就是数据库将数据保存到硬盘等设备上,通过客户端向服务器发送SQL语句来实现数据库的读写操作。关系数据库通过表来管理数据,数据库中可以同时存储多个表,而表是由行和列来组成的,根据SQL语句的内容返回的数据同样必须是二维表的形式。表的列称为字段,表的行称为记录。关系数据库必须以行为单位进行数据读写,行和列交汇的为单元格,一个单元格只能输入一个数据。

SQL是用来操作关系数据库的语言,SQL语言可以分为三类:

  • 数据定义语言DDL:用来创建或者删除存储数据用的数据库以及数据库中的表等对象。

CREATE:创建数据库和表等对象。

DROP:删除数据库和表等对象。

ALTER:修改数据库和表等对象。

  • 数据操纵语言DML:用来查询或者变更表中的记录。

SELECT:查询。

INSERT:向表中插入新数据。

UPDATE: 更新表中的数据。

DELETE:删除表中的数据。

  • 数据控制语言DCL:用来确认或者取消对数据库中的数据进行的变更。

COMMIT: 确认对数据库中的数据进行变更。

ROLLBACK: 取消对数据库中的数据进行变更。

GRANT:赋予用户操作权限。

REVOKE:取消用户操作权限。

作为商业分析师,如果是在业务部门,那实际工作中99%都集中在DML语言中的SELECT。

之后的关卡我们会用到MYSQL,请按照下面的链接一步一步操作,安装好服务器和客户端。

猴子:超级详细的mysql安装指南

猴子:Mysql客户端:Navicat安装教程及问题汇总

安装过程中遇到问题请利用搜索引擎解决,网上也有很多安装教程,请在一天内完成此任务。


关卡2-看完《SQL基础教程》(作者:Mick)-耗时五天

639006a3b63fc4165b9f45e4fde35b6a.png

这本书非常适合初学者,简单易懂,请保证每天看1~2章,书上的例题及课后题目都可以在Navicat上练习,勤做笔记,入门SQL仅此一本书读透彻即可。以下为我看完书后按照章节选取的重要知识点,供参考。强烈建议边看书边自己梳理知识框架,特别是语法运行的逻辑及先后顺序,这对以后编写复杂代码很有用,一定要打好基础。看完一遍后根据框架再快速过一遍来巩固。(第八-九章可以略过,选择性看)

c7a2aff86197da24352000904b6817a3.png

关卡3-上w3school网站查漏补缺-耗时一天

关于学习SQL的网站,我刷过SQLZOO和w3school,但网站上的题目答案不一定是最优的,需要自己去判断和辨别,可以根据个人需要在网站进行学习,不懂的知识点返回《SQL基础教程》去深入理解,会豁然开朗。

SQL 简介

关卡4-入门基础题-耗时三天

网络上流传的入门50题(两个版本都有),先自己做,主要是对之前学的基础知识的巩固和查漏补缺。

  • 第一个版本

学生表 Student(SId,Sname,Sage,Ssex) :

SId 学⽣生编号,Sname 学⽣生姓名,Sage 出⽣生年年⽉月,Ssex 学⽣生性别

课程表 Course(CId,Cname,TId) :

CId 课程编号,Cname 课程名称,TId 教师编号

教师表 Teacher(TId,Tname) :

TId 教师编号,Tname 教师姓名

成绩表 SC(SId,CId,score) :

SId 学⽣生编号,CId 课程编号,score 分数

-- 1、查询01课程比02课程成绩高的学生的信息及课程分数

-- 书写规范:关键词全部大写、括号要缩进并换行

-- 考点1:where 一定要跟select

-- 考点2:匹配join开始运行都是先笛卡尔集,然后根据on后的条件(可多个)重新组合后一定要用select才能取出结果

SELECT e.*,d.cid,d.score FROM

(

SELECT a.sid FROM

(

SELECT sid,cid,score FROM sc

WHERE cid='01'

)AS a

INNER JOIN

(

SELECT sid,cid,score FROM sc

WHERE cid='02'

)AS b

ON a.sid=b.sid

WHERE a.score>b.score

)AS c

LEFT JOIN

sc AS d

ON c.sid=d.sid

LEFT JOIN

student AS e

ON d.sid=e.sid

-- 1.1 查询同时存在课程01和02课程的情况

SELECT d.*,c.cid,c.score FROM

(

SELECT sid,cid,score FROM sc

WHERE cid='01'

)AS a

INNER JOIN

(

SELECT sid,cid,score From sc

WHERE cid='02'

)AS b

ON a.sid=b.sid

LEFT JOIN sc AS c

ON a.sid=c.sid

LEFT JOIN student d

ON c.sid=d.sid

-- 1.2 查询存在01课程但可能不存在02课程的情况(不存在时显示为null)

SELECT d.*,c.cid,c.score FROM

(

SELECT sid,cid,score FROM sc

WHERE cid='01'

)AS a

LEFT JOIN

(

SELECT sid,cid,score From sc

WHERE cid='02'

)AS b

ON a.sid=b.sid

LEFT JOIN sc AS c

ON a.sid=c.sid

LEFT JOIN student d

ON c.sid=d.sid

-- 1.3 查询不存在01课程但存在02课程的情况

SELECT e.*,d.cid,d.score FROM

(

SELECT a.sid FROM

(

SELECT sid,cid,score FROM sc

WHERE cid='02'

)AS a

LEFT JOIN

(

SELECT sid,cid,score From sc

WHERE cid='01'

)AS b

ON a.sid=b.sid

WHERE b.cid is NULL

)AS c

LEFT JOIN sc AS d

ON c.sid=d.sid

LEFT JOIN student AS e

ON d.sid=e.sid

-- 2.查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩

-- 考点:子查询和group by

SELECT a.sid,b.sname,a.score_avg FROM

(

SELECT sid,AVG(score)AS score_avg FROM

sc

GROUP BY sid

) AS a

INNER JOIN

student AS b

ON a.sid=b.sid

WHERE a.score_avg>=60

-- 3、查询在SC表存在成绩的学生信息

SELECT DISTINCT a.* FROM student AS a

INNER JOIN

sc AS b

ON a.sid=b.sid

WHERE b.score is not null

-- 4、查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 null )

SELECT a.sid,a.sname,

COUNT(DISTINCT b.cid)AS '选课总数',

SUM(b.score)AS '课程总成绩'

FROM student AS a

LEFT JOIN

sc AS b

ON a.sid=b.sid

GROUP BY a.sid,a.sname

-- 另外一种是先求分数表先group by 再取对应的学生信息,用子查询

SELECT b.sid,b.sname,a.cid,a.score

FROM

student as b

LEFT JOIN

(

SELECT sid,

COUNT(DISTINCT cid)AS cid,

SUM(score) AS score

FROM sc

GROUP BY sid

)AS a

ON a.sid=b.sid

-- 4.1查有成绩的学生信息

SELECT DISTINCT a.sid,b.sname,b.sage,b.ssex FROM sc AS a

INNER JOIN student AS b

ON a.sid=b.sid

-- 5、查询李姓老师的数量

SELECT COUNT(DISTINCT tid) FROM teacher

WHERE tname LIKE '李%'

-- 6、查询学过张三老师授课的同学信息

SELECT d.sid,c.cid,c.tname,e.sname,e.ssex,e.sage FROM

(

SELECT a.cid,a.tid,b.tname FROM course AS a

INNER JOIN teacher AS b

ON a.tid=b.tid

WHERE tname='张三'

)AS c

LEFT JOIN sc AS d

ON c.cid=d.cid

LEFT JOIN student AS e

ON d.sid=e.sid

-- 7、查询没有学全所有课程的同学信息

SELECT b.sid,c.sname,c.sage,c.ssex FROM

(

SELECT a.sid FROM

(

SELECT sid,COUNT(DISTINCT cid)AS count_cid FROM sc

GROUP BY sid

)AS a

WHERE a.count_cid <3

)AS b

LEFT JOIN student c

ON b.sid=c.sid

-- 所有课程如果不用3直接表示

SELECT b.sid,c.sname,c.sage,c.ssex FROM

(

SELECT a.sid FROM

(

SELECT sid,COUNT(DISTINCT cid)AS count_cid FROM sc

GROUP BY sid

)AS a

WHERE a.count_cid <

(

SELECT COUNT(DISTINCT cid) FROM course

)

)AS b

LEFT JOIN student c

ON b.sid=c.sid

-- 8、查询至少有一门课与学号为01的同学所学相同的同学信息

SELECT DISTINCT a.sid,b.sname,b.ssex,b.sage FROM sc AS a

LEFT JOIN student b

ON a.sid=b.sid

WHERE a.cid IN

(

SELECT cid FROM sc

WHERE sid='01'

)

-- 9查询和01号同学学习的课程完全相同的其他同学的信息

-- concat函数可以连接多个字段

SELECT concat(sid,',',cid,',',score) FROM sc

-- concat_ws()函数可以一次性指定分隔符

SELECT concat_ws(',',sid,cid,score) FROM sc

-- group_concat() 函数让名字出现一次,相同名字对应的id分别出现:语法

SELECT sid,group_concat(cid order by cid DESC separator '_') from sc

GROUP BY sid

-- 先取出01同学学习的课程,并放在一个单元格里作为一个concat_cid,取出其他sid对应的concat_cid让其相等

SELECT a.sid,b.sname,b.sage,b.ssex,group_concat(distinct a.cid order by a.sid,a.cid separator '_')AS concat_cid1

FROM sc AS a

INNER JOIN student AS b

ON a.sid=b.sid

GROUP BY a.sid,b.sname,b.sage,b.ssex

HAVING concat_cid1=

(

SELECT concat_cid FROM

(

SELECT sid,

group_concat(DISTINCT cid order by sid,cid separator '_')AS concat_cid

FROM sc

WHERE sid='01'

GROUP BY sid

)AS score_01

)

--

SELECT a.sid,b.sname,b.sage,b.ssex,group_concat(distinct a.cid order by a.cid separator '_')AS concat_cid1

FROM sc AS a

INNER JOIN student AS b

ON a.sid=b.sid

GROUP BY a.sid,b.sname,b.sage,b.ssex

-- 10、查询没有学过'张三'老师讲授的任一门课程的学生姓名

-- 需要筛选出学过张三老师课程的学生,再进行排除

SELECT sname FROM student

WHERE sid NOT IN

(

SELECT DISTINCT b.sid FROM student AS b

INNER JOIN sc AS c

ON b.sid=c.sid

INNER JOIN course d

ON c.cid=d.cid

INNER JOIN teacher e

ON d.tid=e.tid

WHERE tname='张三'

)

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

SELECT b.sid,d.sname,AVG(c.score) FROM

(

SELECT a.sid FROM

(

SELECT sid,COUNT(DISTINCT cid)as count_cid FROM sc

WHERE score<60

GROUP BY sid

)AS a

WHERE a.count_cid>=2

)AS b

INNER JOIN sc AS c

ON b.sid=c.sid

INNER JOIN student AS d

ON c.sid=d.sid

GROUP BY b.sid

-- 12、取出01课程分数小于60,按分数降序排列的学生信息

SELECT a.* FROM student AS a

INNER JOIN sc AS b

ON a.sid=b.sid

WHERE b.cid='01'

AND b.score<60

ORDER BY b.score DESC

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

SELECT a.*,b.cid,b.score,c.avg_score FROM student AS a

INNER JOIN sc AS b

ON a.sid=b.sid

INNER JOIN

(

SELECT sid,AVG(score)AS avg_score

FROM sc

GROUP BY sid

)AS c

ON b.sid=c.sid

ORDER BY avg_score DESC

-- 14、查询各科成绩最高分、最低分、平均分:

-- 以如下形式显示:课程 ID,课程 name,最⾼高分,最低分,平均分,及格率,中等率,优良率,优秀率

-- 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90

-- 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列

-- 注意count和case when如果取的是0 ,count对于空值也是会计数的

SELECT a.cid,b.cname,

MAX(a.score),

MIN(a.score),

AVG(a.score),

COUNT(a.sid)AS '选修人数',

SUM(case when a.score>=60 then 1 else 0 end)/COUNT(a.sid)AS '及格率',

SUM(case when a.score>=70 and a.score<80 then 1 else 0 end)/COUNT(a.sid) AS '中等率',

SUM(case when a.score>=80 and a.score>=90 then 1 else 0 end)/COUNT(a.sid)AS '优良率',

SUM(case when a.score>80 then 1 else 0 end)/COUNT(a.sid)AS '优秀率'

FROM sc AS a

INNER JOIN course AS b

ON a.cid=b.cid

GROUP BY a.cid,b.cname

ORDER BY '选修人数' DESC ,a.cid

-- 15按各科的成绩进行排序,并显示排名,分数如果重复保留名次空缺

-- 保留名次空缺是指2个80,1个79分,79分排名是第三名。

-- 第一种解法:两个表自连接,通过cid相连,left join 选出A表比B表分数小的,计算比自己大的B表的个数,count+1

SELECT a.sid,a.cid,a.score,count(b.score)+1 AS ranking

FROM sc AS a

LEFT JOIN sc AS b

ON a.cid=b.cid

AND a.score<b.score

GROUP BY a.cid,a.sid,a.score

ORDER BY a.cid,ranking

-- 第二种解法

-- rank() over是跳跃排序的,row_number()over排序唯一值,dense_rank连续排名。,group by 是分组,partition by 是分区

SELECT cid,sid,score,

rank () over (PARTITION BY cid ORDER BY score DESC)AS '排名'

FROM sc

-- 16查询学生的总成绩,并进行排名,总分重复时不保留名次空缺

SELECT a.sid,a.cid,a.score,count(a.score) AS ranking

FROM sc AS a

LEFT JOIN sc AS b

ON a.cid=b.cid

AND a.score<b.score

GROUP BY a.cid,a.sid,a.score

ORDER BY a.cid,ranking

-- 第二种解法

SELECT a.sid,a.sum_score,dense_rank over(ORDER BY a.sum_score) FROM

(

SELECT sid,sum(score)as sum_score

FROM sc GROUP BY sid

)AS a

-- 17、统计各科成绩各分数段人数,课程编号、课程名称,100-85、85-70、70-60、60-0以及所占百分比

SELECT a.cid,b.cname,COUNT(a.sid),

SUM(case when a.score>=85 and a.score<=100 then 1 else 0 end)/COUNT(a.sid)AS '100-85占比',

SUM(case when a.score>=70 and a.score<85 then 1 else 0 end)/COUNT(a.sid)AS '85-70占比',

SUM(case when a.score>=60 and a.score<70 then 1 else 0 end)/COUNT(a.sid)AS '70-60占比',

SUM(case when a.score>=0 and a.score<60 then 1 else 0 end)/COUNT(a.sid)AS '0-60占比'

FROM sc AS a

INNER JOIN course AS b

ON a.cid=b.cid

GROUP BY a.cid,b.cname

-- 18、查询各科成绩前三名的记录

SELECT a.sid,a.cid,a.score,count(b.score)+1 AS ranking

FROM sc AS a

LEFT JOIN sc AS b

ON a.cid=b.cid

AND a.score<b.score

GROUP BY a.cid,a.sid,a.score

HAVING ranking<=3

ORDER BY a.cid,ranking

-- 19、查询每门课被选修的学生数

SELECT cid,COUNT(sid) FROM sc

GROUP BY cid

-- 20、查询出只选修两门课程的学生学号和姓名

SELECT a.*,b.sname FROM

(

SELECT sid,COUNT(cid)as count_cid FROM sc

GROUP BY sid

)AS a

LEFT join student b

ON a.sid=b.sid

WHERE a.count_cid=2

-- 21、查询男生女生人数

SELECT

ssex,COUNT(sid)

FROM

student

GROUP BY ssex

-- 22、查询名字中含有风字的学生信息

SELECT * FROM student

WHERE sname LIKE '%风%'

-- 23、查询同名同姓学生名单,并统计同名人数

SELECT c.sname,COUNT(c.sid)

FROM

(

SELECT a.sname,a.sid from student AS a

INNER JOIN student AS b

ON a.sname=b.sname

AND a.sid<>b.sid

)AS c

GROUP BY c.sname

-- 另一种解法

SELECT sname,COUNT(sid)AS count_sid FROM student

GROUP BY sname

HAVING count_sid>1

-- 24、查询1990年出生的学生名单

SELECT * FROM student

WHERE sage LIKE '%1990%'

-- 另一种解法

SELECT * FROM student

WHERE YEAR(sage)='1990'

-- 25、查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排序

SELECT cid,AVG(score)AS avg_score FROM sc

GROUP BY cid

ORDER BY avg_score DESC ,cid

-- 26、查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩

SELECT a.sid,b.sname,AVG(a.score)AS avg_score FROM

sc AS a

INNER JOIN student AS b

ON a.sid=b.sid

GROUP BY sid

HAVING avg_score>85

-- 27、查询课程名称为数学,且分数低于60的学生姓名和分数

SELECT a.sname,b.score FROM student AS a

INNER JOIN sc AS b

ON a.sid=b.sid

INNER JOIN course AS c

ON b.cid=c.cid

WHERE c.cname='数学'

AND b.score<60

-- 28、查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况)

SELECT a.sid,b.cid,b.score FROM student AS a

LEFT JOIN sc AS b

ON a.sid=b.sid

-- 29、查询任何一门课程成绩在70分以上的姓名、课程名称和分数

SELECT a.sname,b.cid,b.score FROM sc AS b

LEFT JOIN student AS a

ON a.sid=b.sid

WHERE b.score>70

-- 30、查询存在不及格的课程

SELECT cid,sid,score FROM sc

WHERE score<60

-- 31、查询课程编号为01且课程成绩在80分及以上的学生的学号和姓名

SELECT b.sid,b.sname,a.cid,a.score FROM sc AS a

LEFT JOIN student AS b

ON a.sid=b.sid

WHERE a.cid='01'

AND a.score>80

-- 32、求每门课程的学生人数

SELECT cid,COUNT(sid) FROM sc

GROUP BY cid

-- 33、成绩不重复的情况下,查询选修张三老师所授课程的学生中,成绩最高的学生信息以及成绩

-- limit是从表排序第一条开始取的,就算成绩相同也只取一条

SELECT a.sid,a.score,d.sname,d.ssex,d.sage FROM sc AS a

INNER JOIN student AS d

ON a.sid=d.sid

INNER JOIN course AS b

ON a.cid=b.cid

INNER JOIN teacher c

ON b.tid=c.tid

WHERE tname='张三'

ORDER BY a.score DESC

LIMIT 1

-- 34、成绩有重复的情况下,查询选修张三老师所授课程的学生中,成绩最高的学生信息及其成绩

-- 查出最高的这个分数,然后限制得这个分数得所有学生,但仍然要限制课程是张三交的

SELECT f.sid,q.sname,q.ssex,q.sage,f.cid,f.score FROM sc AS f

INNER JOIN student AS q

ON f.sid=q.sid

INNER JOIN course AS w

ON f.cid=w.cid

INNER JOIN teacher AS y

ON w.tid=y.tid

WHERE y.tname='张三'

AND f.score IN

(

SELECT MAX(a.score)AS max_score FROM sc AS a

INNER JOIN student AS d

ON a.sid=d.sid

INNER JOIN course AS b

ON a.cid=b.cid

INNER JOIN teacher c

ON b.tid=c.tid

WHERE tname='张三'

)

-- 35、查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩

SELECT distinct a.sid,a.cid,a.score FROM sc AS a

INNER JOIN sc AS b

ON a.sid=b.sid

AND a.score=b.score

AND a.cid<>b.cid

-- 36、未完成查询每门功课成绩最好的前两名

SELECT cid,count(sid) FROM sc

GROUP BY cid

-- 37、统计每门课程的学生选修人数(超过五人才统计)

SELECT cid,COUNT(sid) FROM sc

GROUP BY cid

HAVING COUNT(sid)>=5

-- 38、取出至少选修两门课的学生学号

SELECT sid,COUNT(cid) FROM sc

GROUP BY sid

HAVING COUNT(cid)>=2

-- 39、查询选修了全部课程的学生信息

-- having这个条件的用法

SELECT a.sid,a.sname,a.ssex,a.sage,COUNT(b.cid)AS count_cid FROM student AS a

INNER JOIN sc AS b

ON a.sid=b.sid

GROUP BY a.sid,a.sname,a.ssex,a.sage

HAVING count_cid =(SELECT count(cid) FROM course)

-- 40、查询学生的年龄,只按年份来

SELECT sid,sname,YEAR(curdate())-YEAR(sage) FROM student

-- 41、按照出生日期来算,当前月<出生年月的月日则年龄减一

-- 时间差函数:

SELECT sid,sname,TIMESTAMPDIFF(YEAR,sage,NOW()) FROM student

-- 42、查出本周过生日的学生

SELECT sid,sname FROM student

WHERE week(sage)=week(curdate())

-- 43、查询下周过生日的学生

SELECT sid,sname FROM student

WHERE week(sage)=week(curdate())+1

-- 44、查询本月过生日的学生

SELECT sid,sname FROM student

WHERE MONTH(sage)=MONTH(curdate())

-- 45、查询下月过生日的学生

SELECT sid,sname FROM student

WHERE MONTH(sage)=MONTH(curdate())+1

  • 第二个版本

首先创建数据:四个表

表student2-字段:s_id(K) ,s_name,s_birth ,s_sex

表course2-字段:c_id(k),c_name,t_id

表teacher2-字段:t_id(k),t_name

表score2-字段:s_id(k),c_id,s_score

1 .查询"01"课程比"02"课程成绩高的学生的信息及课程分数

考点:镶嵌表的自连接

select a.*,b.c_id,b.s_score from student2 a,score2 b where a.s_id=b.s_id

and a.s_id in (select a.s_id from score2 a,score2 b where a.s_id=b.s_id and

a.c_id='01' and b.c_id='02' and a.s_score>b.s_score)

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

考点:按照score2表需要对s_id单个学生的各科平均成绩排序

select s_id,avg(s_score) from score2 group by s_id HAVING avg(s_score)>60 order by s_id

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

考点:两个表的连接,通过s_id,聚合函数count,sum

select a.s_id,a.s_name,count(b.c_id),sum(b.s_score)

from student2 a,score2 b where a.s_id=b.s_id group by a.s_id

4.查询姓“猴”的老师的个数

考点:模糊查询,用like

select t_name,count(t_id) from teacher2 where t_name like '猴%'

5.查询没学过“猴子”老师课的学生的学号、姓名

考点:子查询not in (查询学过猴子老师的学生的学号、姓名)

select a.s_id,a.s_name from student2 a

where a.s_id not in (select b.s_id from score2 b,course2 c,teacher2 d

where b.c_id=c.c_id and c.t_id=d.t_id and d.t_name='猴子')

6.查询学过“猴子”老师所教的所有课的同学的学号、姓名

考点:学生要学过老师教的所有的课,count(学生学过的课)=count(老师教的课),老师教的c_id=学生学的c_id

select a.s_id,a.s_name from student2 a where a.s_id in

(select b.s_id from score2 b,course2 c,teacher2 d

where b.c_id=c.c_id and c.t_id=d.t_id and d.t_name='猴子' group by a.s_id

HAVING count(c.c_id)=(select count(c.c_id) from course2 c,teacher2 d

where c.t_id=d.t_id and d.t_name='猴子' ))

7.查询学过编号为“001”的课程并且也学过编号为“002”的课程的学生的学号、姓名

考点:exist存在,后面接子查询where exists(select.),第二种更加简单,用in (子查询)

select a.s_id,a.s_name,b.c_id from student2 as a ,score2 as b where a.s_id=b.s_id

and b.c_id='01' and EXISTS (select c.c_id from score2 as c where b.s_id=c.s_id

and c.c_id='02')

select a.s_id,a.s_name,b.c_id,b.s_score from student2 a,score2 b where a.s_id=b.s_id

and a.s_id in (select a.s_id from score2 a,score2 b where a.s_id=b.s_id and

a.c_id='01' and b.c_id='02' )

8.查询课程编号为“02”的总成绩

select c_id,sum(s_score) from score2 where c_id='02'

9.查询所有课程成绩小于60分的学生的学号、姓名

select a.s_id,a.s_name from student2 as a ,score2 as b where a.s_id=b.s_id

and b.s_score < 60

10.查询没有学全所有课的学生的学号、姓名

考点:count(学生)<count(c_id)

select a.s_id,a.s_name from student2 as a ,score2 as b where a.s_id=b.s_id group by a.s_id having(count(c_id))<(select count(c_id) from course2)

11.查询至少有一门课与学号为“01”的学生所学课程相同的学生的学号和姓名

考点:c_id in (c_id=01)

select a.s_id,a.s_name from student2 as a,score2 as b where a.s_id=b.s_id

and b.c_id in (select c_id from score2 where s_id='01')

12.查询和“1001”号同学所学课程完全相同的其他同学的学号

考点:要满足in,count(c_id)也要满足

select s_id from score2 where c_id in

(select c_id from score2 where s_id='01') group by s_id

HAVING COUNT(c_id)=(select count(*) from score2 where s_id='01')

13.把“SCORE”表中“猴子”老师教的课的成绩都更改为此课程的平均成绩

考点:更改update表 set 字段=(select) where

update score2 as a set a.s_score=(select avg(b.s_score) from score2

as b where a.c_id=b.c_id ) where a.c_id in (select c_id from course2

as c INNER JOIN teacher2 as d on c.t_id=d.t_id where t_name='猴子')

14.查询和“1002”号的同学学习的课程完全相同的其他同学学号和姓名

select a.s_id,a.s_name from student2 as a INNER JOIN score2 as b on

a.s_id=b.s_id where c_id in (select c_id from score2 where s_id='02')

group by s_id having count(c_id) =(select count(*) from score2 where s_id='02')

17.按平均成绩从高到低显示所有学生的“数据库”(c_id='004')、“企业管理”(c_id='001')、“英语”(c_id='006')三门的课程成绩,按如下形式显示:学生ID,数据库,企业管理,英语,有效课程数,有效平均分

考点:select (select a from A) from B,当A和B是相等的也需要区分

select s_id as 学生ID,

(select s_score from score2 as a where a.s_id=b.s_id and c_id='04') as 数据库,

(select s_score from score2 as a where a.s_id=b.s_id and c_id='01') as 企业管理,

(select s_score from score2 as a where a.s_id=b.s_id and c_id='06') as 英语,

count(*) as 有效课程数,avg(s_score) as 有效平均分 from score2 as b group by s_id ORDER BY avg(s_score) desc

18.查询各科成绩最高和最低的分: 以如下的形式显示:课程ID,最高分,最低分

select c_id as 课程ID,max(s_score) as 最高分,min(s_score) as 最低分 from score2

group by c_id

19.按各科平均成绩从低到高和及格率的百分数从高到低排列,以如下形式显示:

考点:sum(case when 条件s_score>60 then 结果 1 else 0 end)/cpunt(*)

select a.c_id as 课程号,a.c_name as 课程名,avg(b.s_score)as 平均成绩,

sum(case when s_score>=60 then 1 else 0 end)/count(*) as 及格百分比

from course2 as a INNER JOIN score2 as b on a.c_id=b.c_id group by a.c_id

order by sum(case when s_score>=60 then 1 else 0 end)/count(*) DESC

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

select a.t_name,b.c_id,avg(b.s_score)from score2 as b,course2 as c,teacher2

as a where a.t_id=c.t_id and c.c_id=b.c_id group by b.c_id

order by avg(b.s_score) desc

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

考点:分段用case when,前面可以接聚合函数

select course2.c_id as 课程ID,course2.c_name as 课程名称,

sum(case when s_score between 85 and 100 then 1 else 0 end )as '85-100',

sum(case when s_score between 70 and 85 then 1 else 0 end )as '70-85',

sum(case when s_score between 60 and 70 then 1 else 0 end )as '60-70',

sum(case when s_score <60 then 1 else 0 end )as '60-'

from score2,course2 where score2.c_id=course2.c_id

group by score2.c_id

24.查询学生平均成绩及其名次

考点:一、排序有三种函数,rank/dense_rank/row_number三种,具体用法如下:rank()over(partition by order by) 排序为1,1,1,4;dense_rank() over (partition by order by)排序为1,1,1,2;row_number()over (partition by order by)排序为1,2,3,4;二、order by 和where后面不能接聚合函数,from 后面加子查询,先找出学生的学号和对应的平均成绩,并对平均成绩进行命名a,之后才用order by;三、有聚合函数,考虑要用到group by 四、row_number()over 可以不加partition by ,加了的话是对内部再次进行排序。

select a.s_id,a.amt,rownumber()over (order by a.amt desc) from (select s_id,avg(s_score) as amt from score2 group by s_id)as a

25.查询各科成绩前三名的记录(不考虑成绩并列情况)

考点:运行的顺序,where 和select是并列的,先运行from后面的子查询(先写出按照各科成绩排名的结果,没有聚合函数一般不用group by,用order by可以实现;这里需要按各科内排序用partition by;)命名为a ,再在外面写select * from ()as a where a.字段

select * from(

select c_id,s_score,row_number()over(partition by c_id order by s_score desc)as ti

FROM score2) a

where a.ti<=3

26.查询每门课程被选修的学生数

select c_id,count(s_id) from score2 group by c_id

27.查询出只选修了一门课程的全部学生的学号和姓名

select a.s_id,b.s_name,count(a.c_id)from student2 as b,score2 as a where a.s_id=b.s_id

group by a.s_id having count(a.c_id)=1

28.查询男生、女生人数

select count(s_sex) as 男生人数 from student2 where s_sex='男'

group by s_sex

select count(s_sex) as 女生人数 from student2 where s_sex='女'

group by s_sex

29.查询姓“张”的学生名单

select * from student2 where s_name like '张%'

30.查询同名同性学生名单并统计同名人数

select *,count(s_name) from student2 group by s_name

having count(s_name)>1

31.1981年出生的学生名单(注:Student表中s_birth列的类型是datetime)

考点:trunc(字段)=当前日期,只适用于oracle,trunc(字段,'mm')返回当月第一天,trunc(字段,'yy')返回当年第一天;

select * from student2 where trunc(s_birth,'yyyy')='1981-01-01'

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

select a.s_id,a.s_name,avg(b.s_score)from student2 a,score2 b where a.s_id=

b.s_id group by a.s_id having avg(b.s_score)>85

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

select avg(s_score) from score2 group by c_id order by avg(s_score),c_id DESC

34.查询课程名称为“数据库”且分数低于60的学生姓名和分数

select a.s_name,b.s_score from student2 as a,score2 as b,course2 as c

where a.s_id=b.s_id and b.c_id=c.c_id and c.c_name='数据库' and b.s_score<60

35.查询所有学生的选课情况

select a.s_id,a.s_name,c.c_name from student2 a,score2 b,course2 c

where a.s_id=b.s_id and b.c_id=c.c_id

36.查询任何一门课程成绩在70分以上的姓名、课程名称和分数

select a.s_name,c.c_name,b.s_score from student2 a,score2 b,course2 c

where a.s_id=b.s_id and b.c_id=c.c_id and b.s_score>70 group by a.s_id

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

select c_id from score2 where s_score<60 order by c_id

38.查询课程编号为003且课程成绩在80分以上的学生的学号和姓名

select a.s_id,a.s_name from student2 a ,score2 b where a.s_id=b.s_id

and b.s_score>80 and b.c_id='03'

39.查询选了课程的学生人数

select count(s_id) from score2

40.查询选修“猴子”老师所授课程的学生中成绩最高的学生姓名及其成绩

select a.s_name,max(b.s_score) from student2 as a,score2 as b,course2

as c,teacher2 as d

where a.s_id=b.s_id and b.c_id=c.c_id and c.t_id=d.t_id

and d.t_name='猴子'

41.查询各个课程及相应的选修人数

select count(s_id) from score2 group by c_id

42.查询有2门不同课程成绩相同的学生的学号、课程号、学生成绩

select a.s_id,a.c_id,b.s_score from score2 as a ,score2 as b

where a.s_id=b.s_id and a.s_score=b.s_score and a.c_id<>b.c_id

43.查询每门课程成绩最好的前两名

select * from (select s_id,c_id,s_score,row_number()over(partition by c_id order by s_score desc)as ti from score2 ) as a where a.ti<=2

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

select c_id,count(s_id) from score2 group by c_id having count(s_id)>10

order by s_id desc,c_id asc

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

select s_id from score2 group by s_id having count(c_id)>=2

46.查询全部学生都选修的课程的课程号和课程名

select c_id,c_name from course2 where c_id in (select c_id from score2 group by c_id)

47.查询没学过“猴子”老师讲授的任一门课程的学生姓名

select s_name from student2 where s_id not in

(select s_id from course2,teacher2,score2 where course2.t_id=teacher2.t_id

and score2.c_id=course2.c_id and t_name='猴子')

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

select s_id,avg(s_score) from score2 where s_score< 60 group by s_id

having count(c_id)>2

49.检索课程编号为“004”且分数小于60的学生学号,结果按按分数降序排列

select s_id from score2 where c_id='04' and s_score<60 order by s_score DESC

50.删除学生编号为“002”的课程编号为“001”的成绩

delete from score2 where s_id='02' and c_id='01'

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值