資料庫(一)-- 常用查詢語句
很多查詢都可以用經典的學生-課程-成績案例來表示,下面是一些我在筆試或面試中遇到的經典題型。這些題目沒有涉及到索引,函式,儲存過程等高階功能,都是一些基本的查詢語句,但難度卻不小。
表結構
- 學生表student(id,name)
- 學生課程表student_course(sid,cid,score)
問題
1. 查詢student表中重名的學生,結果包含id和name,按name,id升序
2. select id,name
3. from student
4. where name in (
5. select name from student group by name having(count(*) > 1)
6. ) order by name,id;
我們經常需要查詢某一列重複的行,一般通過group by(有重複的列)然後取count>1的值。 關係型資料庫有他的侷限性, 有些看似簡單的查詢寫出來的sql很複雜,而且效率也會很低。
7. 在student_course表中查詢平均分不及格的學生,列出學生id和平均分
8. select sid,avg(score) as avg_score
9. from student_course
10. group by sid having(avg_score<60);
group by和having是最常考的。 where子句中不能用聚集函式作為條件表示式,但是having短語可以,where和having的區別在於對用物件不同,where作用於記錄,having作用於組
11. 在student_course表中查詢每門課成績都不低於80的學生id
12. select distinct sid
13. from student_course
14. where sid not in (
15. select sid from student_course
16. where score < 80);
用到反向思想,其實就是數理邏輯中的∀
x:P
和
¬
∃
x:
¬
P
是等價的。
17. 查詢每個學生的總成績,結果列出學生姓名和總成績 如果使用下面的sql會過濾掉沒有成績的人
18. select name,sum(score) total
19. from student,student_course
20. where student.id=student_course.sid
21. group by sid;
更保險的做法應該是使用**左外連線**
select name,sum(score)
from student left join student_course
on student.id=student_course.sid
group by sid;
22. 總成績最高的學生,結果列出學生id和總成績 下面的sql效率很低,因此要重複計算所有的總成績。
23. select sid,sum(score) as sum_score
24. from student_course group by sid having sum_score>=all
25. (select sum(score) from student_course group by sid);
因為order by中可以使用聚集函式,最簡單的方法是:
select sid,sum(score) as sum_score
from student_course group by sid
order by sum_score desc limit 1;
同理可以查總成績的前三名。
26. 在student_course表查詢課程1成績第2高的學生,如果第2高的不止一個則列出所有的學生 先查出第2高的成績:
27. select min(score) from student_course where cid = 1 order by score desc limit 2;
然後再取出該成績對應的學生:
select * from student_course
where cid=1 and score = (
select min(score)
from student_course where cid = 1 order by score desc limit 2);
類似的,可以查詢**某個值第N高**的記錄。
28. 在student_course表查詢各科成績最高的學生,結果列出學生id、課程id和對應的成績 你可能會這樣寫:
29. select sid,cid,max(score) from student_course group by cid;
然而上面是不對的,因為**使用了group by的查詢欄位只能是group by中的欄位或者聚集函式**。 雖然不會報錯,但是sid是無效的,如果去掉sid的話只能查出沒門課程的最高分,不包含學生id。 本題的正確解法是使用相關巢狀查詢:
select * from A as x where score>=
(select max(score) from A as y where y.clsid=x.clsid);
相關巢狀查詢也就是在進行內層查詢的時候需要用到外層查詢,有一些注意事項:
- 子查詢一定要有括號
- as可以省略
- 使用相關查詢;>=max等價於>=all,但是聚合函式比使用any或all效率高
30. 在student_course表中查詢每門課的前3名,結果按班級課程id升序,同一課程按成績降序 類似的查詢在csdn上也有徵集答案
31. select * from student_course x where
32. 3>(select count(*) from student_course y where y.cid=x.cid and y.score>x.score)
33. order by cid,score desc;
這也是一個相關巢狀查詢,對於每一個分數,如果同一門課程下只有0個、1個或2個分數比這個分數還高,那麼這個分數肯定是前3名之一
34. 一個叫team的表,裡面只有一個欄位name,一共有4條紀錄,分別是a,b,c,d,對應四個球隊,兩兩進行比賽,用一條sql語句顯示所有可能的比賽組合
35. select a.name, b.name
36. from team a, team b
37. where a.name < b.name
其實就是一個表和自己連線查詢。
38. 題目:資料庫中有一張如下所示的表,表名為sales。
年 |
季度 |
銷售 |
1991 |
1 |
11 |
1991 |
2 |
12 |
1991 |
3 |
13 |
1991 |
4 |
14 |
1992 |
1 |
21 |
1992 |
2 |
22 |
1992 |
3 |
23 |
1992 |
4 |
24 |
39. 要求:寫一個SQL語句查詢出如下所示的結果。
年 |
一季度 |
二季度 |
三季度 |
四季度 |
1991 |
11 |
12 |
13 |
14 |
1992 |
21 |
22 |
23 |
24 |
40. select 年,
41. sum(case when 季度=1 then 銷售量 else 0 end) as 一季度,
42. sum(case when 季度=2 then 銷售量 else 0 end) as 二季度,
43. sum(case when 季度=3 then 銷售量 else 0 end) as 三季度,
44. sum(case when 季度=4 then 銷售量 else 0 end) as 四季度
45. from sales group by 年;