刷到一个小公司的sql面试题,记录一下思路

1、现有一张表ainfo,表数据如下:

Id

Name

Age

Birth

Sex

Memo

1

徐洪国

23

1998-03-23


本科

2

王芳芳

26

1995-10-11


高中

3

徐风年

24

1997-04-09


硕士

4

李明

30

1991-11-23


大专

5

郑洋

27

1994-12-28


博士

6

-

-

-

-

-

1)请编写SQL语句对年龄进行升序排列
SELECT * FROM AINFO ORDER BY AGE ASC; 
--  ASC升序 DESC倒序
2)请编写SQL语句查询对“徐”姓开头的人员名单
SELECT * FROM AINFO WHERE NAME LIKE '徐%';
-- % 通配符 代表零个或多个字符
-- _ 通配符 仅一个字符
3)请统计表中男女各有多少人?
SELECT Sex,COUNT(Sex) FROM  AINFO GROUP BY Sex;
-- GROUP BY 针对某些数据进行分组,并可以拿到分组数据中,对应聚合函数的值,例如MAX(Sex)、MIN(Sex)等;
也可以实现去重的功能
4)现有一张表 binfo字段和 ainfo相同请编写SQL语句将 ainfo中的表备份到 binfo中
-- 先建表 后插入数据
CREATE TABLE BINFO LIKE AINFO;
INSERT INTO BINFO SELECT * FROM AINFO;
-- 或者  
-- 在表不存在的情况下,也可以直接备份目标表
CREATE TABLE BINFO AS SELECT * FROM AINFO;

2、现有一张表 user_score,结构如下:

Name

Kecheng

Fenshu

张三

语文

81

张三

数学

75

李四

语文

76

李四

数学

90

王五

语文

81

王五

数学

100

王五

英语

90

1)用一条SQL语句查询出每门课都大于80分的学生姓名
SELECT NAME 
FROM
	USER_SCORE 
WHERE
	NAME NOT IN ( SELECT NAME FROM USER_SCORE WHERE FENSHU <= 80 GROUP BY NAME ) 
GROUP BY
NAME
-- 1、首页我们拿到在这个表中FENSHU低于80的人并根据NAME进行分组  拿到分数低于80的人
-- 2、再用NOT IN这个表排除掉 1)中的数据就可以拿到正确结果集
2)查询出各科的平均成绩,显示字段为:学科,平均分
SELECT
	KECHENG AS 学科,
	AVG( FENSHU ) AS 平均分 
FROM
	USER_SCORE 
GROUP BY
	KECHENG
-- AS 可以为某一列或者某一张表,起一个别名
-- AVG() 拿到某一列的平均值
3)查询出单科成绩最高的,显示字段为:姓名,学科,成绩
SELECT
	B.* 
FROM
	( SELECT MAX(FENSHU) FENSHU, KECHENG FROM USER_SCORE GROUP BY KECHENG ) A
	LEFT JOIN USER_SCORE B ON A.FENSHU = B.FENSHU 
	AND A.KECHENG = B.KECHENG
-- 1.先通过GROUP BY KECHENG 对课程进行分组,拿到每门课程最高的分数
-- 2.再通过 LEFT JOIN(左连接) USER_SCORE 用,对应课程的分数与最高分数 进行对比,拿到人员的姓名

3、一个叫team的表,里面只有一个字段name,一共有4条纪录,分别是a,b,c,d,对应四个球队、,现在四个球队进行比塞,用一条SQL语句显示所有可能的比赛组合

SELECT
	B.NAME,
	C.NAME 
FROM
	TEAM B
	LEFT JOIN TEAM C ON B.NAME != C.NAME
-- 利用LEFT JOIN的特性让两个表的记录(相乘) 再通过NAME进行排除

4、现在有下面四张表,请按照要求编写SQL语句

Student( s_no, sname, sage,sex)学生表
Course( c_no cname,t_no)课程表
Sc( s_no,c_no, score)成绩表
Teacher( t_no, tname)教师表

1)查询“001"课程比“002"课程成绩高的所有学生的学号
SELECT
	A.S_NO 
FROM
	( SELECT * FROM SC WHERE C_NO = '001' ) A,
	( SELECT * FROM SC WHERE C_NO = '002' ) B 
WHERE
	A.S_NO = B.S_NO 
	AND A.SCORE > B.SCORE
======= 等价与
SELECT
	A.S_NO 
FROM
	( SELECT * FROM SC WHERE C_NO = '001' ) A
	INNER JOIN
	( SELECT * FROM SC WHERE C_NO = '002' ) B 
WHERE
	A.S_NO = B.S_NO 
	AND A.SCORE > B.SCORE
-- 1.将课程001与002的成绩都查阅出来,
-- 2.根据条件筛选是否为同一个学生,再筛选 001成绩比002好的学校的工号
2)检索至少选修了两门课程的学生学号
SELECT
	S_NO,
	COUNT( S_NO ) 
FROM
	SC 
GROUP BY
	S_NO 
HAVING
	COUNT( S_NO ) > 2 
-- 1.查询成绩表,拿到学校总共有多少门成绩,根据GROUP BY S_NO来对学号进行分组,
-- 2.对记录数大于2(选修了几门课)的数据进行筛选
-- HAVING字句可以让我们筛选成组后的各种数据,字句在聚合前先筛选记录,也就是说作用在GROUP BY和HAVING字句前,而 HAVING子句在聚合后对组记录进行筛选。我的理解就是真实表中没有此数据,这些数据是通过一些函数生存
-- 简单来说就是,HAVING 可以对分组后的数据进行对应的筛选,而WHERE是针对GROUP BY之前的数据进行筛选。
3)查询学过“001”并且也学过编号“"002”课程的同学的学号、姓名。
SELECT
	S_NO,
	SNAME 
FROM
	STUDENT 
WHERE
	S_NO IN 
	(
	SELECT
		A.S_NO 
	FROM
		( SELECT * FROM SC WHERE C_NO = '1' ) A,
		( SELECT * FROM SC WHERE C_NO = '2' ) B 
	WHERE
		A.S_NO = B.S_NO 
	)
-- 1.拿到学过001与002的学生列表,并进行内连接
-- 2.再针对这些数据进行工号的比对,查询该行记录是否学号相同,相同代表学生学过001,也学过002
4)查询至少学过学号为“001"同学所有一门课的其他同学学号和姓名。(题目有点绕,学习过001同学所有课名中其中一门的学号,及姓名)
SELECT
	S_NO,
	SNAME 
FROM
	STUDENT 
WHERE
	S_NO IN (
	SELECT
		S_NO 
	FROM
		SC 
	WHERE
		C_NO IN ( SELECT C_NO FROM SC WHERE S_NO = '001' ) 
		AND S_NO != '001' 
	GROUP BY
	S_NO)
-- 1.首先拿到 学习001一共学习了几门课程
-- 2.排除001对应的行的数据,再根据学号对数据进行GROUP BY分组(分组可以去重)
5)查询选修了“冯老师”所授课程的学生中,成绩最高的学生姓名及其成绩
SELECT
	N.SNAME,
	F.SCORE 
FROM
	(SELECT E.S_NO,D.SCORE FROM
		(SELECT C_NO,MAX( SCORE ) SCORE FROM SC WHERE
			C_NO IN 
			( SELECT C_NO FROM TEACHER A LEFT JOIN COURSE B ON A.T_NO = B.T_NO WHERE A.TNAME = '叶平' ) 
		GROUP BY
			C_NO 
		) D
		LEFT JOIN SC E ON D.C_NO = E.C_NO 
		AND D.SCORE = E.SCORE 
	) F
	LEFT JOIN STUDENT N ON N.S_NO = F.S_NO
-- 1.首页拿到’冯老师‘ 所授课程的C_NO
-- 2.再根据所有的课程分组拿到每门课程的最高的最高分
-- 3.再通过左连接拿到对应学生的学号
-- 4.再连接学生信息表拿到学生姓名
6)查询两门以上不及格课程的同学的学号及其平均成绩
SELECT
	S_NO,
	AVG( SCORE ) 
FROM
	SC 
WHERE
	S_NO IN ( SELECT S_NO FROM SC WHERE SCORE < 60 GROUP BY S_NO HAVING COUNT( C_NO )>= 2 ) 
GROUP BY
	S_NO
-- 1.根据成绩表拿到所有不及格的成绩,并根据S_NO进行分组 再通过 HAVING COUNT( C_NO )>= 2 拿到不及格课程>=2的人有哪些
-- 2.再去查询成绩表根据筛选后的数据进行分组,拿到对应学生的学号,与平均值
7)查询选修了所有课程的学生学号和姓名
SELECT
	S_NO,
	SNAME 
FROM
	STUDENT 
WHERE
	S_NO IN (
	SELECT
		S_NO 
	FROM
		SC 
	GROUP BY
		S_NO 
	HAVING
		COUNT( C_NO )= ( SELECT COUNT(*) FROM COURSE ))
-- 1.先拿到一共有几门课程
-- 2.再根据成绩表分组,判断学生所学的课程总数是不是等于总课程的
-- 3.最后根据S_NO学生信息表拿到对应学生的姓名跟NO