1. 程式人生 > >資料庫(一)-- 常用查詢語句

資料庫(一)-- 常用查詢語句

很多查詢都可以用經典的學生-課程-成績案例來表示,下面是一些我在筆試或面試中遇到的經典題型。這些題目沒有涉及到索引,函式,儲存過程等高階功能,都是一些基本的查詢語句,但難度卻不小。

表結構

  • 學生表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 年;