SQL面試50題——學(xué)習(xí)記錄(二)

# 第11題:查詢至少有一門課與學(xué)號為“01”的學(xué)生所學(xué)課程相同的學(xué)生的學(xué)號和姓名

SELECT stu.s_id 學(xué)號,s_name 姓名 FROM student stu JOIN  (

SELECT DISTINCT s_id

FROM score s RIGHT JOIN (SELECT c_id FROM score WHERE s_id = "01") a ON s.c_id= a.c_id

WHERE s.s_id<>"01")b ON stu.s_id = b.s_id;

/* 以上是自己的解法棚点,此題思路是先找出學(xué)號為01的學(xué)生所學(xué)的課程尊搬,然后把結(jié)果當(dāng)成主表與score表

以c_id相等為條件進行外連接,這樣就把所有有相同課程的人給找出來了途样。

在多表進行聯(lián)合查詢的時候江醇,若查詢的字段在兩個表都有的情況下,這些字段前必須加上表名何暇。

比如此題的stu.s_id 前必須加上stu 而s_name則無需加上stu

*/

#第11題老師的寫法如下:

SELECT a.s_id,a.s_name FROM student AS a

INNER JOIN(

SELECT DISTINCT s_id FROM score

WHERE c_id IN (

SELECT c_id FROM score

WHERE s_id ="01"

)AND s_id !="01"

)AS b ON a.s_id=b.s_id;

# 第12題:查詢與學(xué)號為“01”的學(xué)生所學(xué)課程完全相同的學(xué)生的學(xué)號和姓名

SELECT stu.s_id 學(xué)號,s_name 姓名 FROM student stu JOIN  (

SELECT s.s_id FROM  score s

LEFT JOIN (SELECT c_id FROM score WHERE s_id = "01") a

ON s.c_id= a.c_id

WHERE s.s_id<>"01" AND a.c_id IS NOT NULL

GROUP BY s.s_id

HAVING COUNT( DISTINCT s.c_id)= (SELECT COUNT(c_id) FROM score WHERE s_id = "01" )

)b ON stu.s_id = b.s_id

/* 以上是自己的解法陶夜,此題思路與第11題大致類似,先找出學(xué)號為01的學(xué)生所學(xué)的課程裆站,然后把此結(jié)果當(dāng)成從表與

主表score以c_id相等為條件進行外連接(那么此時會行成一個表条辟,大致為:凡是與01號學(xué)生所學(xué)課程相同的那一行數(shù)據(jù),從表的

c_id列都會有該課程的id宏胯,其余為null),所以只需要把01號學(xué)升自己排除且把從表的c_id字段為null的行排除后羽嫡,按照s_id進行

分組,然后統(tǒng)計課程數(shù)(需要使用distinct胳嘲,用于排重)與01號學(xué)生學(xué)的課程一樣就行了厂僧。

我在做這題的時候,有2個沒考慮周全的問題了牛。

1:count()是按照*颜屠、s.c_id來的,沒有對s.c_id去重

2:沒有排除a.c_id 為null的數(shù)據(jù),這樣會帶入臟數(shù)據(jù)鹰祸。比如有個學(xué)生學(xué)的課程id是7 8 9甫窟,也就意味著該學(xué)生有3行a.c_id列為null的

數(shù)據(jù),統(tǒng)計時會把該學(xué)生統(tǒng)計進去蛙婴。

總結(jié):這題我感覺還是蠻麻煩的粗井,很多細節(jié)點。

*/

# 第12題:老師的寫法(他貌似第一次也寫錯了街图,考慮的不周全)

SELECT * FROM student

WHERE s_id IN (

SELECT s_id FROM score

WHERE s_id!="01"

GROUP BY s_id HAVING COUNT(DISTINCT c_id)=(SELECT COUNT(DISTINCT c_id) FROM score WHERE s_id="01")

)

AND s_id NOT IN (

SELECT DISTINCT s_id FROM score

WHERE c_id NOT IN(

SELECT c_id FROM score

WHERE s_id="01")

)

# 第13浇衬、14題這邊沒看到題目,所以就沒貼了餐济。為了保證與其同步后面好復(fù)習(xí)耘擂,我也就直接跳到15題了

# 第15題:查詢2門及以上不及格(score<60)的同學(xué)的學(xué)號、姓名及其平均成績

SELECT  s.s_id 學(xué)號, stu.s_name 姓名, AVG(s_score)平均成績 

FROM  score s JOIN  student  stu

ON s.s_id = stu.s_id

WHERE s_score< 60

GROUP BY s.s_id

HAVING COUNT(DISTINCT s.c_id)>=2;

/* 這題比較簡單絮姆,就是先聯(lián)合查詢醉冤,然后篩選出哪些課的成績是小于60的秩霍,然后再按照id進行分組,

再利用count統(tǒng)計結(jié)果蚁阳,count內(nèi)用distinct是為了排重铃绒,有可能某個人的一門課有2次成績,當(dāng)然這個

要看設(shè)計表時如何設(shè)計的螺捐,我就根據(jù)自己的習(xí)慣加上了颠悬。

*/

# 第15題老師的做法

SELECT a.s_id,a.s_name,AVG(s_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(DISTINCT c_id)>=2

)

GROUP BY s_id,s_name;

# 第16題: 檢索“01”課程分數(shù)小于60,按分數(shù)降序排列的學(xué)生信息

SELECT s.s_id 學(xué)號,s_name 性名,s_sex 性別,s_birth 出生日期,c_id 課程,s_score 分數(shù)

FROM score s JOIN student stu

ON s.s_id = stu.s_id

WHERE c_id = "01" AND s_score<60

ORDER BY s_score DESC;

# 第17題 :按平均成績從高到低顯示所有學(xué)生的所有課程的成績以及平均成績

SELECT s.s_id 學(xué)號,s.c_id 課程,s.s_score 成績, a.平均成績  平均成績

FROM  score  s LEFT JOIN (SELECT s_id,AVG(s_score) 平均成績 FROM score GROUP BY s_id) a

ON s.s_id = a.s_id

ORDER BY 平均成績 DESC,成績 DESC;

我的寫法看起來不舒服归粉,不符合日常需求椿疗。如下:

image

# 第17題老師的寫法,這種方法我覺得還是很6的

SELECT s_id 學(xué)號

,MAX(CASE WHEN c_id="01" THEN s_score ELSE NULL END) 語文

,MAX(CASE WHEN c_id="02" THEN s_score ELSE NULL END) 數(shù)學(xué)

,MAX(CASE WHEN c_id="03" THEN s_score ELSE NULL END) 英語

,AVG(s_score)  平均成績

FROM  score 

GROUP BY s_id

ORDER BY 平均成績 DESC;

執(zhí)行結(jié)果如下:

image

/*

老師這種方法我覺得還是很6的糠悼,

巧用了case when then 與 max()

該題注意的點是届榄,使用 group by后select后必須是被分組的字段或者是聚合函數(shù),

具體講解見:https://blog.csdn.net/qq403580298/article/details/90756352

因按照s_id分組后倔喂,每個c_id其實只有一個值铝条,所以使用max/min/avg等聚合函數(shù)都OK

最后取得數(shù)都是一樣的

對了 在使用case when 的時候 經(jīng)常漏掉后面的end

*/

# 第18題: 查詢各科成績最高分、最低分席噩、平均分班缰、及格率,中等率悼枢,優(yōu)良率埠忘,優(yōu)秀率:及格>=60,中等為[70,80),優(yōu)良為:[80,90),優(yōu)秀為>=90

SELECT s.c_id 課程id

,c_name 課程名

,MAX(s_score) 最高分

,MIN(s_score) 最低分

,AVG(s_score) 平均分

,SUM(CASE WHEN s_score>=60 THEN 1 ELSE 0 END)/COUNT(s_score) 及格率

,SUM(CASE WHEN s_score>=70 AND s_score<80 THEN 1 ELSE 0 END)/COUNT(s_score) 中等率

,SUM(CASE WHEN s_score>=80 AND s_score<90 THEN 1 ELSE 0 END)/COUNT(s_score) 優(yōu)良率

,SUM(CASE WHEN s_score>=90 THEN 1 ELSE 0 END)/COUNT(s_score) 優(yōu)秀率

FROM score s JOIN course c

ON s.c_id = c.c_id

GROUP BY s.c_id;

執(zhí)行結(jié)果如下:

image

/*

此題主要難點是在求各個課程的及格率馒索、中等率..上

思路與17題類似 巧用了 case when then else與 sum()莹妒。

即設(shè)定一個條件,當(dāng)分數(shù)滿足這個條件時+1绰上,不滿足時+0旨怠。

另外補充一個把小數(shù)轉(zhuǎn)換成百分數(shù)的方法:

select concat(0.6667*100,'%') 得出的結(jié)果為:66.6700%

此時會覺得保留小數(shù)后兩位比較好,那么可以這樣寫:select concat(round(0.6667*100,2),'%')

所以針對上面的SQL可以寫成如下(看起來比較繞):

*/

SELECT s.c_id 課程id

,c_name 課程名

,MAX(s_score) 最高分

,MIN(s_score) 最低分

,ROUND(AVG(s_score),2) 平均分

,CONCAT(ROUND(SUM(CASE WHEN s_score>=60 THEN 1 ELSE 0 END)/COUNT(s_score)*100,2),'%')及格率

,CONCAT(ROUND(SUM(CASE WHEN s_score>=70 AND s_score<80 THEN 1 ELSE 0 END)/COUNT(s_score)*100,2),'%') 中等率

,CONCAT(ROUND(SUM(CASE WHEN s_score>=80 AND s_score<90 THEN 1 ELSE 0 END)/COUNT(s_score)*100,2),'%') 優(yōu)良率

,CONCAT(ROUND(SUM(CASE WHEN s_score>=90 THEN 1 ELSE 0 END)/COUNT(s_score)*100,2),'%') 優(yōu)秀率

FROM score s JOIN course c

ON s.c_id = c.c_id

GROUP BY s.c_id;

改進后執(zhí)行如下:

image

# 第19題 :按各科成績進行排序蜈块,并顯示排名

#rank()over()的使用

SELECT s.s_id 學(xué)號,s_name 姓名,c_name 課程,s_score 成績

,rank()over(PARTITION BY s.c_id ORDER BY s_score DESC) 科內(nèi)排名

FROM student stu

JOIN score s ON stu.s_id = s.s_id

JOIN course c ON s.c_id = c.c_id;

#執(zhí)行結(jié)果如下

image

#rank()over()的使用,不使用partition by的效果

SELECT s.s_id 學(xué)號,s_name 姓名,c_name 課程,s_score 成績

,rank()over(ORDER BY s_score DESC) 科內(nèi)排名

FROM student stu

JOIN score s ON stu.s_id = s.s_id

JOIN course c ON s.c_id = c.c_id;

#執(zhí)行結(jié)果如下

image

#row_number()over()的使用

SELECT s.s_id 學(xué)號,s_name 姓名,c_name 課程,s_score 成績

,row_number()over(PARTITION BY s.c_id ORDER BY s_score DESC) 科內(nèi)排名

FROM student stu

JOIN score s ON stu.s_id = s.s_id

JOIN course c ON s.c_id = c.c_id;

#執(zhí)行結(jié)果如下

image

#dense_rank()over()的使用

SELECT s.s_id 學(xué)號,s_name 姓名,c_name 課程,s_score 成績

,dense_rank()over(PARTITION BY s.c_id ORDER BY s_score DESC) 科內(nèi)排名

FROM student stu

JOIN score s ON stu.s_id = s.s_id

JOIN course c ON s.c_id = c.c_id;

#執(zhí)行結(jié)果如下

image

/*

總結(jié):

row_number()over(partition by字段1 order by 字段2) 的結(jié)果是每一行記錄生成一個序號鉴腻,依次排序且排序的序號不會重復(fù)

rank()over(partition by字段1 order by 字段2) 的結(jié)果會考慮排序字段值相同的情況,若排序字段的值相同則其序號是一樣的百揭,

后續(xù)不同字段值的序號為(前一行序號+N,其中N為前一個字段值重復(fù)的行數(shù))爽哎,比如 1 1 3 4 4 4 7。

dense_rank()over(partition by字段1 order by 字段2) 的結(jié)果也會考慮排序字段值相同的情況器一,即排序字段的值相同那么他們的序號是一樣的课锌,但是與rank()的區(qū)別是后續(xù)不同字段值的序號為(前一行序號+1),比如 1 1 2 2 3 4 5

另外:over(partition by字段1 order by 字段2)中的partition by 字段1 是可以省略的但是order by 字段2 不可省略

*/

#第20題:對學(xué)生總成績從大到小排序

SELECT stu.s_id 學(xué)號, stu.s_name 姓名

,SUM(s.s_score) 總成績,rank () over (ORDER BY SUM(s.s_score) DESC) 排名

FROM student stu

JOIN score s ON stu.s_id = s.s_id

GROUP BY stu.s_id;

#執(zhí)行結(jié)果如下

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載盹舞,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者产镐。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市踢步,隨后出現(xiàn)的幾起案子癣亚,更是在濱河造成了極大的恐慌,老刑警劉巖获印,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件述雾,死亡現(xiàn)場離奇詭異,居然都是意外死亡兼丰,警方通過查閱死者的電腦和手機玻孟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鳍征,“玉大人黍翎,你說我怎么就攤上這事⊙薮裕” “怎么了匣掸?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長氮双。 經(jīng)常有香客問我碰酝,道長,這世上最難降的妖魔是什么戴差? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任送爸,我火速辦了婚禮,結(jié)果婚禮上暖释,老公的妹妹穿的比我還像新娘袭厂。我一直安慰自己,他們只是感情好饭入,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布嵌器。 她就那樣靜靜地躺著,像睡著了一般谐丢。 火紅的嫁衣襯著肌膚如雪爽航。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天乾忱,我揣著相機與錄音讥珍,去河邊找鬼。 笑死窄瘟,一個胖子當(dāng)著我的面吹牛衷佃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蹄葱,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼氏义,長吁一口氣:“原來是場噩夢啊……” “哼锄列!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起惯悠,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤邻邮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后克婶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體筒严,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年情萤,在試婚紗的時候發(fā)現(xiàn)自己被綠了鸭蛙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡筋岛,死狀恐怖娶视,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情睁宰,我是刑警寧澤歇万,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站勋陪,受9級特大地震影響贪磺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜诅愚,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一寒锚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧违孝,春花似錦刹前、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至校坑,卻和暖如春拣技,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背耍目。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工膏斤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人邪驮。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓莫辨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沮榜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 這50題是網(wǎng)上經(jīng)典的SQL題目盘榨,先嘗試自己寫,然后與老師的寫法做對比蟆融。在這個過程中我會把我犯的錯较曼,以及把老師的寫法...
    順子哥66的閱讀 992評論 0 5
  • 表名和字段 --插入學(xué)生表測試數(shù)據(jù)insert into Student values('01' , '趙雷' ,...
    C1R2閱讀 5,330評論 0 1
  • 二刷經(jīng)典SQL面試50題,當(dāng)當(dāng)振愿,決定將解法重新梳理一遍。從一刷的磕磕絆絆弛饭,自己就是常見錯誤解法冕末,到二刷思維...
    jinghenggl閱讀 744評論 0 2
  • 推薦指數(shù): 6.0 書籍主旨關(guān)鍵詞:特權(quán)、焦點侣颂、注意力档桃、語言聯(lián)想、情景聯(lián)想 觀點: 1.統(tǒng)計學(xué)現(xiàn)在叫數(shù)據(jù)分析憔晒,社會...
    Jenaral閱讀 5,721評論 0 5
  • 城空了拒担,有樹長出來 我的城死了 鑄起它的人嘹屯,殺死它的人 不愿因為這件事而驕傲 一座城的終結(jié) 永遠因為終結(jié)這件事而顯...
    于十六閱讀 2,859評論 6 17