c语言解析sql语句_sql语句面试50题(Mysql版附解析)
本人最近在自學sql,從開始學到自己寫完本練習50題大概花了12天的時間。
學習路徑:《sql基礎教程》第1遍(3天)→知乎中的sql網課+leetcode刷題(4天)→牛客網刷題(2天)→《sql基礎教程》第2遍(1晚上)→sql面試練習50題(3天)
文中的代碼都是按自己思路寫的,大家在做題的時候最好也按照自己的思路來寫,實在想不通的再參考我的思路,畢竟每個人的編寫思路不一樣,唯有自己思考過才會印象深刻。有問題的小伙伴可以評論留言,一起探討~
表名和字段
Student(s_id,s_name,s_birth,s_sex) --學生編號,學生姓名, 出生年月,學生性別
–2.課程表
Course(c_id,c_name,t_id) – --課程編號, 課程名稱, 教師編號
–3.教師表
Teacher(t_id,t_name) --教師編號,教師姓名
–4.成績表
Score(s_id,c_id,s_score) --學生編號,課程編號,分數
測試數據
--建表
--學生表
CREATE TABLE `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`)
);
--課程表
CREATE TABLE `Course`(`c_id` VARCHAR(20),`c_name` VARCHAR(20) NOT NULL DEFAULT '',`t_id` VARCHAR(20) NOT NULL,PRIMARY KEY(`c_id`)
);
--教師表
CREATE TABLE `Teacher`(`t_id` VARCHAR(20),`t_name` VARCHAR(20) NOT NULL DEFAULT '',PRIMARY KEY(`t_id`)
);
--成績表
CREATE TABLE `Score`(`s_id` VARCHAR(20),`c_id` VARCHAR(20),`s_score` INT(3),PRIMARY KEY(`s_id`,`c_id`)
);
--插入學生表測試數據
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' , '女');
--課程表測試數據
insert into Course values('01' , '語文' , '02');
insert into Course values('02' , '數學' , '01');
insert into Course values('03' , '英語' , '03');--教師表測試數據
insert into Teacher values('01' , '張三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');--成績表測試數據
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);練習題目及sql語句
1、查詢"01"課程比"02"課程成績高的學生的信息及課程分數
-- [分析] 篩選出課程號01這門課的成績比02這門課成績高的學生,輸出這些學生的信息及課程分(表:Student,Score)——表聯結
select a.*, b.s_score as 01_score, c.s_score as 02_score
from Student as a inner join Score as b on a.s_id = b.s_id and b.c_id = '01'
inner join Score as c on a.s_id = c.s_id and c.c_id = '02'
where b.s_score > c.s_score;2、查詢"01"課程比"02"課程成績低的學生的信息及課程分數
-- [分析] 與上體的思路一樣,換個符合方向就可
select a.*, b.s_score as 01_score, c.s_score as 02_score
from student as a inner join score as b on a.s_id = b.s_id and b.c_id = '01'
inner join score as c on a.s_id = c.s_id and c.c_id = '02'
where b.s_score < c.s_score;3、查詢平均成績大于等于60分的同學的學生編號和學生姓名和平均成績
-- [分析] 要求平均成績,就需要用group by對學生分組,然后利用聚合函數avg求出平均成績,由于where語句中不能包含聚合函數,故再利用having語句和60分比較。
-- 輸出的結果學生編號和學生姓名在student表中,成績在score表中,故需要用到內聯結。
select a.s_id, a.s_name, avg(s_score) as avg_score
from student as a inner join score as b on a.s_id = b.s_id
group by a.s_id,a.s_name
having avg(b.s_score) >= 60;4、查詢平均成績小于60分的同學的學生編號和學生姓名和平均成績
-- [分析] 和3題思路一樣,改個符號方向即可
select a.s_id, a.s_name, avg(s_score) as avg_score
from student as a inner join score as b on a.s_id = b.s_id
group by b.s_id
having avg(b.s_score) < 60;5、查詢所有同學的學生編號、學生姓名、選課總數、所有課程的總成績
-- [分析]學生編號、學生姓名在表student中;選課數可通過在表score中通過group by 學生編號后利用count(c_id)算出;所有課程的總成績則用sum可以算出。
-- 因為要用到表student和表score,故需要對表進行聯結。
select a.s_id, a.s_name, count(b.c_id), sum(b.s_score)
from student as a inner join score as b on a.s_id = b.s_id
group by a.s_id,a.s_name;6、查詢"李"姓老師的數量
-- [分析] 這里用到知識點字符串模糊查詢,如:where 姓名 like '猴%' 即可查到猴什么什么。
-- 關于字符串模糊查詢的知識點可查看我的另一篇文章《SQL學習筆記——匯總分析》
select count(t_name) as number
from teacher
where t_name like '李%';7、查詢學過"張三"老師授課的同學的信息
-- [分析] 老師的信息在表teacher中,可通過teacher.t_id與表course聯結,
-- 再通過course.c_id與表score聯結,
-- 再再通過score.s_id與表student聯結,查找出上過張三老師課的同學的信息。
select s.*
from teacher as a inner join course as b on a.t_id = b.t_id
inner join score as c on b.c_id = c.c_id
inner join student as s on c.s_id = s.s_id
where a.t_name = '張三';8、查詢沒學過"張三"老師授課的同學的信息
-- [分析]這里不能直接將“=”替換成“<>”,因為不等于張三時,還有別的老師。所以要用到子查詢來解決。
select *
from student
where s_id not in
(select s.s_id
from teacher as a inner join course as b on a.t_id = b.t_id
inner join score as c on b.c_id = c.c_id
inner join student as s on c.s_id = s.s_id
where a.t_name = '張三');9、查詢學過編號為"01"并且也學過編號為"02"的課程的同學的信息
-- [分析]由于既要學過01課程的,又要學過02課程的,所以共需要聯結兩次才能達到篩選效果
select *
from student
where s_id in (select a.s_id from student as a inner join score as b on a.s_id = b.s_id and b.c_id = '01' inner join score as c on b.s_id = c.s_id and c.c_id = '02');10、查詢學過編號為"01"但是沒有學過編號為"02"的課程的同學的信息
-- [分析] 在上述語句中用and聯結,注意不能直接將“=”換成“<>”
select *
from student
where s_id in (select a.s_id from student as a inner join score as b on a.s_id = b.s_id and b.c_id = '01')
and s_id not in (select a.s_id from student as a inner join score as c on a.s_id = c.s_id and c.c_id = '02');11、查詢沒有學全所有課程的同學的信息
-- [分析]沒學全所有課程的情況很多,如學0門,學1門,學2門。所以這里先篩選出學全所有課程的同學再取反,即沒有學全所有課程的同學。
select *
from student
where s_id not in (select s_id from score group by s_id having count(c_id) = (select count(distinct c_id) from course));12、查詢至少有一門課與學號為"01"的同學所學相同的同學的信息 *
-- [分析]子查詢兩次,第一次找到學號為01的同學所學的課程,第二次再找到至少一門課與學號01同學上的課相同的同學信息
select *
from student
where s_id in (select distinct a.s_id from score as a where a.c_id in(select b.c_id from score as b where b.s_id = '01')) and s_id <> '01';-- 方法2:內聯結+一次子查詢
select distinct a.*
from student as a inner join score as b on a.s_id = b.s_id
where b.c_id in (select c_id from score where s_id = '01')
and b.s_id <> '01' ;13、查詢和"01"號的同學學習的課程完全相同的其他同學的信息 (不會)
-- [分析] 利用子查詢 查出學號01的課程數 再去找課程數一樣的其他同學
select student.*
from student
where s_id in (select s_id from score group by s_id having count(c_id) = (select count(c_id) from score where s_id = '01')
and s_id <> '01');14、查詢沒學過"張三"老師講授的任一門課程的學生姓名
-- [分析] 方法一:瘋狂子查詢
select s_name
from student
where s_id not in (select s_id from score where c_id = (select c_id from coursewhere t_id = (select t_id from teacher where t_name = '張三'))); 方法二:子查詢+內聯結
select s_name
from student
where s_id not in (select a.s_id from score as a inner join course as b on a.c_id = b.c_idinner join teacher as c on b.t_id = c.t_id and c.t_name = '張三');15、查詢兩門及其以上不及格課程的同學的學號,姓名及其平均成績
-- [分析] 內聯結+篩選
select a.s_id,a.s_name,avg(b.s_score) as avg_score
from student as a inner join score as b on a.s_id = b.s_id
where a.s_id in (select s_id from score where s_score < 60 group by s_id having count(s_score) >= 2)
group by a.s_id,a.s_name; -- where篩選出來后一定不要忘記分組顯示!!!
-- 方法2 (簡單)
select a.s_id,a.s_name,avg(b.s_score)
from student as a inner join score as b on a.s_id = b.s_id and b.s_score < 60
group by a.s_id,a.s_name
having count(b.s_score) >= 2;16、檢索"01"課程分數小于60,按分數降序排列的學生信息
-- [分析] 內聯結+子查詢篩選+排序
select a.*,b.c_id,b.s_score
from student as a inner join score as b on a.s_id = b.s_id and b.c_id = 01
where a.s_id in (select s_id from score where s_score < 60 order by s_score desc);17、按平均成績從高到低顯示所有學生的所有課程的成績以及平均成績(重要!)
select a.s_id,(select s_score from score where s_id = a.s_id and c_id = '01') as 語文,(select s_score from score where s_id = a.s_id and c_id = '02') as 數學,(select s_score from score where s_id = a.s_id and c_id = '03') as 英語,round(avg(s_score),2) as 平均分
from score as a
group by a.s_id
order by 平均分 desc;-- 18.查詢各科成績最高分、最低分和平均分:以如下形式顯示:課程ID,課程name,最高分,最低分,平均分,及格率,中等率,優良率,優秀率--及格為>=60,中等為:70-80,優良為:80-90,優秀為:>=90(重要!)
-- [分析] 用到case語句,后面記得按課程號分組來顯示全部結果
select a.c_id,a.c_name,max(b.s_score),min(b.s_score),avg(b.s_score),round(100*(sum(case when b.s_score >= 60 then 1 else 0 end)/sum(case when b.s_score then 1 else 0 end)),2) as 及格率,round(100*(sum(case when b.s_score between 70 and 80 then 1 else 0 end)/sum(case when b.s_score then 1 end)),2) as 中等率,round(100*(sum(case when b.s_score between 80 and 90 then 1 else 0 end)/sum(case when b.s_score then 1 end)),2) as 優良率,round(100*(sum(case when b.s_score >= 90 then 1 else 0 end)/sum(case when b.s_score then 1 end)),2) as 優秀率
from course as a inner join score as b on a.c_id = b.c_id
group by a.c_id,a.c_name;19、按各科成績進行排序,并顯示排名(涉及到TopN問題,重要!!!)
-- [分析] 本題涉及到窗口函數的使用 重點記住語句:dense_rank() over (partition by 列名 order by 排序用列 desc
select s_id, c_id, s_score, dense_rank() over (PARTITION by c_id order by s_score desc) as rank_
from score;20、查詢學生的總成績并進行排名
select s_id,sum(s_score)
from score
group by s_id
order by sum(s_score) desc;21、查詢不同老師所教不同課程平均分從高到低顯示
select a.t_id,avg(b.s_score)
from course as a inner join score as b on a.c_id = b.c_id
group by a.t_id
order by avg(b.s_score) desc;22、查詢所有課程的成績第2名到第3名的學生信息及該課程成績
select a.*,sum(b.s_score)
from student as a inner join score as b on a.s_id = b.s_id
group by s_id -- 一定不要忘記分組啊啊啊啊啊!
order by sum(b.s_score) desc
limit 1,2 -- 1代表把排名第一的數去了,2代表去除第一名后往下篩選兩個出來23、統計各科成績各分數段人數:課程編號,課程名稱,[100-85],[85-70],[70-60],[0-60]及所占百分比
select a.c_id, a.c_name,
sum(case when b.s_score between 85 and 100 then 1 else 0 end) as '100-85',
round(100*(sum(case when b.s_score between 85 and 100 then 1 end)/sum(case when b.s_score then 1 end)),2),
sum(case when b.s_score between 70 and 85 then 1 end) as '85-70',
round(100*(sum(case when b.s_score between 75 and 85 then 1 end)/sum(case when b.s_score then 1 end)),2),
sum(case when b.s_score between 60 and 70 then 1 end) as '70-60',
round(100*(sum(case when b.s_score between 60 and 70 then 1 end)/sum(case when b.s_score then 1 end)),2),
sum(case when b.s_score < 60 then 1 end) as 不及格,
round(100*(sum(case when b.s_score <=60 then 1 end)/sum(case when b.s_score then 1 end)),2)
from course as a inner join score as b on a.c_id = b.c_id
group by a.c_id,a.c_name24、查詢學生平均成績及其名次
select s_id,avg(s_score),rank() over (order by avg(s_score) desc) as rank_score
from score
group by s_id25、查詢各科成績前三名的記錄(重要!!!!!)
-- [分析]這道題最簡單的寫法就是分別寫出課程號,然后用union關鍵字合并
(select * from score where c_id = '01' order by s_score desc limit 3)
UNION
(select * from score where c_id = '02' order by s_score desc limit 3)
UNION
(select * from score where c_id = '03' order by s_score desc limit 3);26、查詢每門課程被選修的學生數
-- [分析] 有點簡單,寫完甚至有點難以置信,還親自去數了一遍。。。。。。
select c_id, count(s_id)
from score
group by c_id;27、查詢出只有兩門課程的全部學生的學號和姓名
-- [分析] 內聯結+篩選
select a.s_id,a.s_name
from student as a inner join score as b on a.s_id = b.s_id
group by a.s_id
having count(b.c_id) = 2;28、查詢男生、女生人數
方法1:
select s_sex,count(s_sex) as 人數
from student
group by s_sex;
方法2:
(select s_sex,count(s_sex) as 人數 from student where s_sex = '男')
union
(select s_sex,count(s_sex) as 人數 from student where s_sex = '女')29、查詢名字中含有"風"字的學生信息
-- [分析] 考察字符串模糊查詢,之前我的sql學習筆記中有詳細記錄https://zhuanlan.zhihu.com/p/128093194
select *
from student
where s_name like "%風%";30、查詢同名同性學生名單,并統計同名人數(重要!!!!!)
-- [分析] 將表student定義兩次,然后進行內聯結,并給出判斷條件
select a.s_name,a.s_sex,count(*)
from student as a inner join student as b on a.s_id <> b.s_id and a.s_name = b.s_name and a.s_sex = b.s_sex
group by a.s_name,a.s_sex;31、查詢1990年出生的學生名單
-- [分析] 字符串模糊查詢
select *
from student
where s_birth like "1990%";32、查詢每門課程的平均成績,結果按平均成績降序排列,平均成績相同時,按課程編號升序排列
-- [分析] 考察order by 語句的升降序及先后次序
select c_id,avg(s_score)
from score
group by c_id
order by avg(s_score) desc,c_id asc;33、查詢平均成績大于等于85的所有學生的學號、姓名和平均成績
select a.s_id, a.s_name, avg(b.s_score)
from student as a inner join score as b on a.s_id = b.s_id
group by b.a_id,a.s_name
having avg(b.s_score) >= 85;34、查詢課程名稱為"數學",且分數低于60的學生姓名和分數
-- [分析] 三個表聯結,兩個篩選條件:①c.cname = '數學' ②b.s_score < 60
select a.s_name, b.s_score
from student as a inner join score as b on a.s_id = b.s_id
inner join course as c on b.c_id = c.c_id and c.c_name = '數學'
where b.s_score < 60;35、查詢所有學生的課程及分數情況;
select a.s_id, b.c_id, b.c_name, a.s_score
from score as a inner join course as b on a.c_id = b.c_id;36、查詢任何一門課程成績在70分以上的姓名、課程名稱和分數;
select a.s_name,c.c_name,b.s_score
from student as a inner join score as b on a.s_id = b.s_id
inner join course as c on c.c_id = b.c_id
where b.s_score >= 70;37、查詢不及格的課程
select a.s_id,a.s_name,c.c_id,c.c_name,b.s_score
from student as a inner join score as b on a.s_id = b.s_id
inner join course as c on b.c_id = c.c_id
where b.s_score < 60;38、查詢課程編號為01且課程成績在80分以上的學生的學號和姓名;
select a.s_id,a.s_name
from student as a inner join score as b on a.s_id = b.s_id
where b.c_id = '01' and b.s_score >= 80;39、求每門課程的學生人數
select a.c_id,a.c_name,count(b.s_id)
from course as a inner join score as b on a.c_id = b.c_id
group by b.c_id;40、查詢選修"張三"老師所授課程的學生中,成績最高的學生信息及其成績
select d.*,max(c.s_score)
from teacher as a inner join course as b on a.t_id = b.t_id
inner join score as c on c.c_id = b.c_id
inner join student as d on d.s_id = c.s_id
where a.t_name = '張三'41、查詢不同課程成績相同的學生的學生編號、課程編號、學生成績 (重要!!!!)
select distinct b.s_id,b.c_id,b.s_score
from score as a,score as b
where a.c_id != b.c_id and a.s_score = b.s_score42、查詢每門功成績最好的前兩名
-- [分析]這道題不吹牛逼,我認為我的寫法最牛逼
(select c_id,s_score from score where c_id = '01' order by s_score desc limit 2)
UNION
(select c_id,s_score from score where c_id = '02' order by s_score desc limit 2)
UNION
(select c_id,s_score from score where c_id = '03' order by s_score desc limit 2)43、統計每門課程的學生選修人數(超過5人的課程才統計)。要求輸出課程號和選修人數,查詢結果按人數降序排列,若人數相同,按課程號升序排列
select c_id,count(s_id)
from score
group by c_id
having count(s_id) >= 5
order by count(s_id) desc,c_id asc;44、檢索至少選修兩門課程的學生學號
select s_id,count(c_id)
from score
group by s_id
having count(c_id) >= 2;45、查詢選修了全部課程的學生信息
select a.*
from student as a inner join score as b on a.s_id = b.s_id
group by s_id
having count(b.c_id) = (select count(c_id) from course);46、查詢各學生的年齡 按照出生日期來算,當前月日 < 出生年月的月日則,年齡減一
-- [分析] 這道題俺不會,學sql 的時候沒學日期函數的使用,答案是查來的
select 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 0 else 1 end)) as age
from student;47、查詢本周過生日的學生
select * from student where WEEK(DATE_FORMAT(NOW(),'%Y%m%d'))=WEEK(s_birth)
select * from student where YEARWEEK(s_birth)=YEARWEEK(DATE_FORMAT(NOW(),'%Y%m%d'))
select WEEK(DATE_FORMAT(NOW(),'%Y%m%d'))48、查詢下周過生日的學生
select*from student where WEEK(DATE_FORMAT(NOW(),'%Y%m%d'))+1=WEEK(s_birth)49、查詢本月過生日的學生
select*from student whereMONTH(DATE_FORMAT(NOW(),'%Y%m%d'))=MONTH(s_birth)50、查詢下月過生日的學生
select*from student whereMONTH(DATE_FORMAT(NOW(),'%Y%m%d'))+1=MONTH(s_birth)
總結
以上是生活随笔為你收集整理的c语言解析sql语句_sql语句面试50题(Mysql版附解析)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求一个好听的酒店管理公司名字。
- 下一篇: python时间序列动图_手把手教你用P