MySQL查詢語句經典練習題拆解思路(一)

今天工做不忙,心血來潮找了幾個SQL語句練習題來作,一作才發現,基本功仍是不紮實.網上找的練習題只有答案,沒有解題思路,遂寫下這篇帖子,梳理解題流程, 請大牛多多指教.性能

表名和字段
–1.學生表
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(spa

`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(.net

`c_id`  VARCHAR(20),
`c_name` VARCHAR(20) NOT NULL DEFAULT '',
`t_id` VARCHAR(20) NOT NULL,
PRIMARY KEY(`c_id`)

);
--教師表
CREATE TABLE Teacher(code

`t_id` VARCHAR(20),
`t_name` VARCHAR(20) NOT NULL DEFAULT '',
PRIMARY KEY(`t_id`)

);
--成績表
CREATE TABLE Score(blog

`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' , '王五');get

--成績表測試數據
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);
原文連接:https://blog.csdn.net/fashion...數學

題:一、查詢"01"課程比"02"課程成績高的學生的信息及課程分數
下面附上解題思路分析:it

那位大牛寫的標準答案:
select a.* ,b.s_score as 01_score,c.s_score as 02_score from
student a
join score b on a.s_id=b.s_id and b.c_id='01'
left join score c on a.s_id=c.s_id and
c.c_id='02' or c.c_id = NULL where b.s_score>c.s_score
image.png

拆解:

(1)先查出全部學生的課程1的分數及該學生信息

select a.* ,b.s_score as 01_score from student a join score b on a.s_id=b.s_id and b.c_id='01'

image.png

(2) 再用左外聯接查出這些學生課程2的分數,由於吳蘭02課程沒有考,因此空.

select a.* ,b.s_score as 01_score,c.s_score as 02_score from

student a

join score b on a.s_id=b.s_id and b.c_id='01'

left join score c on a.s_id=c.s_id and c.c_id='02'

image.png

上邊的第二個鏈接不能用內鏈接,由於內鏈接只顯示雙方條件都符合的,即兩個課程都參加考試了的,因此就不會顯示吳蘭的信息了.

請注意,上邊的left join的主體是第一次join以後的臨時表,而不是原student表,每一個join或者left join的主體都是前面的臨時表,除非只有一個join..

(3)、最後一步,在最後加上where條件 b.s_score > c.s_score ,即課程1分數 > 課程2分數

注: 在使用left join時,on and和on where條件的區別以下:
I、on條件是在生成臨時表時使用的條件,它無論on中的條件是否爲真,都會返回左邊表中的記錄。
II、where條件是在臨時表生成好後,再對臨時表進行過濾的條件。這時已經沒有left join的含義(必須返回左邊表的記錄)了,條件不爲真的就所有過濾掉,on後的條件用來生成左右表關聯的臨時表,where後的條件對臨時表中的記錄進行過濾。是最後一步總篩選.
III、where中不能用別名01_score,02_score,不然會提示沒有此字段,這是基本常識,不過仍是要提醒一下,共勉.

標準答案里加了個or c.c_id = NULL 這個加不加都行,由於這裏是比較課程1課程2的,
且前面有and c.c_id='02'了,這一步不會執行(由於會短路求值)若是c_id爲NULL,那全部的課程2分數都爲NULL, 就沒有比較的意義了.

第二種解法是這樣:
select a.*,b.s_score as 01_score,c.s_score as 02_score from student a,score b,score c
where a.s_id=b.s_id
and a.s_id=c.s_id
and b.c_id='01'
and c.c_id='02'
and b.s_score>c.s_score

此寫法比較好理解,雖然不夠優雅,可是性能好.第一種寫法的聯查很費性能,在開發中能不用就不用.

相關文章
相關標籤/搜索