表准備:
這次我們用到5張表:
class表:
student表:
score表:
course表:
teacher表:
表結構模型:
我們針對以下需求分析聯表查詢:
1、查詢所有的課程的名稱以及對應的任課老師姓名
2、查詢平均成績大於八十分的同學的姓名和平均成績
3、 查詢沒有報李平老師課的學生姓名
4、 查詢選修物理課程和體育課程其中一門的學生姓名
5、 查詢掛科超過兩門(包括兩門)的學生姓名和班級
6、找出同時選了李平老師所有課的學生班級和姓名
1、查詢所有的課程的名稱以及對應的任課老師姓名
分析需求:我們需要用到course和teacher表:既需要得到課程名稱又要拿到老師姓名,然后看表結構模型,我們可以知道course有外鍵字段teacher_id指向teacher表id,那么我們就可以用內連接inner join將兩張表拼接起來然后取其字段course.cname和teacher.tname即可得到我們想要的數據,SQL語句如下:
SELECT cname, tname FROM teacher INNER JOIN course ON course.teacher_id = teacher.tid;
2、查詢平均成績大於八十分的同學的姓名和平均成績
需求分析:我們需要用到score表和shtudent表,既要拿到學生姓名又要拿到成績,我們理所當然需要將這兩個表聯表或者做子連接,然后需求中需要用到平均數,那么我們應想到用聚合函數avg(),但使用聚合函數的前提是分組(不人為分組時默認整個表就是一個組) group by,下面我們來寫sql語句:
首先在聯表或子連接前可以通過score表分組得到student_id和平均成績:
select student_id,avg(num) as avg_score from score group by student_id having avg(num) >80;
然后在以上虛擬表的基礎上通過student_id拼接student表,取student.sname和avg_score即可
SELECT student.sname, k.avg_score FROM student INNER JOIN ( SELECT student_id, avg( num ) AS avg_score FROM score GROUP BY student_id HAVING avg( num ) > 80 ) AS k ON k.student_id = student.sid;
3、 查詢沒有報李平老師課的學生姓名
需求分析:我們根據表結構得知我們需要用到student,score,course,teacher這4張表,直接得到沒有報李平老師課程的學生比較困難,那么我們就反過來想,哪些是報了李平老師課程的,然后在學生表里剔除掉即可:
首先我們可以先得到李平老師教了哪幾門課,用course和teacher聯表:
select course.cid,course.cname from course inner join teacher on course.teacher_id = teacher.tid where teacher.tname = "李平老師";
根據表結構我們可以知道,course表和score表通過外鍵連接,那么我們就可以把上面得到的虛擬表和score表子查詢,取字段score.student_id即可得到所有選了李平老師課程的學生id,然后根據student_id分組或去重就可以得到不重名的學生id選了李平老師課程的虛擬表:
select score.student_id from score where course_id in ( select course.cid from course inner join teacher on course.teacher_id = teacher.tid where teacher.tname = "李平老師" ) ;
然后將上面得到的虛擬表與student表做子連接的條件得到選了李平老師課程的學生姓名,然后我們not in即可得到需求
select sname from student where sid not in ( select score.student_id from score where course_id in ( select course.cid from course inner join teacher on course.teacher_id = teacher.tid where teacher.tname = "李平老師" ) );
4、 查詢選修物理課程和體育課程的其中一門的學生姓名
需求分析:需要通過課程得到學生姓名,通過表結構我們可以得知,需要用到 student、score、course表,需要得到選了這兩門課程的學生姓名,那我們就可以通過course表先拿到物理課和體育課對應的id,然后把這個id作為score表的查詢條件查出對應的student_id,然后我們可以對student_id進行分組后用having過濾掉group_concat(student_id)大於等於2的部分,即可得到只選修了這兩門課程中其中一門的學生id,然后我們可以拿這個結果去作為student表的子連接條件得到學生姓名,sql語句如下:
SELECT student.sname FROM student WHERE sid IN ( SELECT student_id FROM score WHERE course_id IN ( SELECT cid FROM course WHERE cname IN ( "物理", "體育" ) ) GROUP BY student_id HAVING count( student_id ) = 1 );
第二種查詢方法:
SELECT k.sname, k.course_id FROM course INNER JOIN ( SELECT student.sname, score.course_id FROM student INNER JOIN score ON score.student_id = student.sid ) AS k ON course.cid = k.course_id WHERE course.cname IN ( "物理", "體育" ) GROUP BY k.sname HAVING count( k.sname ) = 1;
5、 查詢掛科超過兩門(包括兩門)的學生姓名和班級
需求分析:這個需求和第四個需求類似,我們可以先拿到所有掛科的學生id,然后進行分組,篩選出掛科數大於等於2的一部分學生id,然后把取到的id作為student表的查詢條件去取學生姓名即可,sql語句如下:
SELECT caption, k.sname FROM class INNER JOIN ( SELECT sname, class_id FROM student WHERE sid IN ( SELECT student_id FROM score WHERE num < 60 GROUP BY student_id HAVING count( student_id ) >= 2 ) ) k ON k.class_id = class.cid;
6、找出同時選了李平老師所有課的學生班級和姓名
需求分析:需要用到班級和老師,那么5張表都要用到,我們還是套用前面的方法,先通過teacher表找到李平老師的id,通過這個id在course表里找到李平老師的課程表的id,然后拿這個id去score表里找選了李平老師課程的student_id,這時候我們要對student_id進行分組了,篩選出含2個以上的student_id,再通過得到的student_id去student_表里找到對應的姓名和class_id,然后將生成的虛擬表去和class表聯表,取出class.cname和student.sname即是我們想要的數據,sql語句如下:
SELECT class.caption, n.sname FROM class INNER JOIN ( SELECT class_id, sname FROM student WHERE sid IN ( SELECT student_id FROM ( SELECT student_id, course_id FROM score WHERE course_id IN ( SELECT course.cid FROM teacher INNER JOIN course ON course.teacher_id = teacher.tid WHERE teacher.tid = 2 ) ) AS k GROUP BY student_id HAVING count( student_id ) = 2 ) ) AS n ON class.cid = n.class_id ORDER BY n.sname;
今天的聯表查詢到這里就結束啦!給個贊唄~