 # 1. 問題4 ## 1.1. 最多選修兩門課程的學生,沒有選修任何課程的學生應該被排除在外 ## 1.2. ...
1. 問題4
1.1. 最多選修兩門課程的學生,沒有選修任何課程的學生應該被排除在外
1.2. sql
select distinct s.*
from student s, take t
where s.sno = t.sno
and s.sno not in ( select t1.sno
from take t1, take t2, take t3
where t1.sno = t2.sno
and t2.sno = t3.sno
and t1.cno < t2.cno
and t2.cno < t3.cno )
1.3. 兩次自連接的解決方案避免了聚合運算
1.4. 基於SNO的內連接操作能夠確保子查詢返回的每一行都是針對同一個學生的數據
1.5. 子查詢就是為了找出選修了3門以上課程的學生
1.6. 外層查詢則負責返回至少選修了一門課程,並且SNO不存在於子查詢返回結果的學生
1.7. DB2
1.8. Oracle
1.9. SQL Server
1.10. 視窗函數COUNT OVER
1.10.1. sql
select distinct sno,sname,age
from (
select s.sno,s.sname,s.age,
count(*) over (
partition by s.sno,s.sname,s.age
) as cnt
from student s, take t
where s.sno = t.sno
)x
where cnt <= 2
1.11. PostgreSQL
1.12. MySQL
1.13. 聚合函數COUNT判斷哪些學生最多選修了兩門課程
1.13.1. sql
select s.sno,s.sname,s.age
from student s, take t
where s.sno = t.sno
group by s.sno,s.sname,s.age
having count(*) <= 2
1.14. 計算出TAKE表中每個SNO出現的次數
1.15. STUDENT表和TAKE表的內連接操作能夠確保剔除掉沒有選修任何課程的學生
2. 問題5
2.1. 年齡最多大於其他兩名同學的學生
2.1.1. 比其他0個、1個或者2個學生年齡大的學生
2.2. sql
select *
from student
where sno not in (
select s1.sno
from student s1,
student s2,
student s3,
student s4
where s1.age > s2.age
and s2.age > s3.age
and s3.age > s4.age
)
SNO SNAME AGE
--- ---------- ---
6 JING 18
4 MAGGIE 19
1 AARON 20
9 GILLIAN 20
8 KAY 20
3 DOUG 20
2.3. 找出比其他3個或更多學生年齡大的學生集合
2.3.1. 大於具有傳遞性
2.4. 為提高可讀性,使用DISTINCT壓縮結果集
2.5. 在子查詢中使用NOT IN就可以篩選出除了上述4人之外的那些學生
2.6. DB2
2.7. Oracle
2.8. SQL Server
2.9. 視窗函數DENSE_RANK
2.9.1. sql
select sno,sname,age
from (
select sno,sname,age,
dense_rank()over(order by age) as dr
from student
) x
where dr <= 3
2.10. 視窗函數DENSE_RANK根據有多少人比當前學生年齡小計算出每個學生對應的排名
2.11. DENSE_RANK不僅允許Tie的存在,還能保證名次連續,中間不留空白
2.12. PostgreSQL
2.13. MySQL
2.14. 聚合函數COUNT和關聯子查詢
2.14.1. sql
select s1.*
from student s1
where 2 >= ( select count(*)
from student s2
where s2.age <s1.age )
2.15. 聚合函數解決方案使用標量子查詢篩選出最多比其他兩名學生年齡大的學生
3. 問題6
3.1. 至少選修了兩門課程的學生
3.2. sql
select *
from student
where sno in (
select t1.sno
from take t1,
take t2
where t1.sno = t2.sno
and t1.cno > t2.cno
)
SNO SNAME AGE
--- ---------- ----------
1 AARON 20
3 DOUG 20
4 MAGGIE 19
6 JING 18
3.3. 子查詢里的SNO相等條件能夠確保每個學生只與自己的選課信息相比較
3.4. CNO大於比較條件,只有在一個學生至少選修了一門課程的情況下才會成立,否則CNO會等於另一個CNO
3.4.1. 只有一門課程,只能和自身比較
3.5. DB2
3.6. Oracle
3.7. SQL Server
3.8. 視窗函數COUNT OVER
3.8.1. sql
select distinct sno,sname,age
from (
select s.sno,s.sname,s.age,
count(*) over (
partition by s.sno,s.sname,s.age
) as cnt
from student s, take t
where s.sno = t.sno
) x
where cnt >= 2
3.9. 使用STUDENT表的全部列定義分區並執行COUNT OVER操作
3.10. 只要保留那些CNT大於或者等於2的行即可
3.11. PostgreSQL
3.12. MySQL
3.13. 聚合函數COUNT
3.13.1. sql
select s.sno,s.sname,s.age
from student s, take t
where s.sno = t.sno
group by s.sno,s.sname,s.age
having count(*) >= 2
3.14. HAVING子句中使用COUNT篩選出那些選修了兩門以上課程的學生
4. 問題7
4.1. 同時選修了CS112和CS114兩門課程的學生
4.2. sql
select s.*
from student s,
take t1,
take t2
where s.sno = t1.sno
and t1.sno = t2.sno
and t1.cno = 'CS112'
and t2.cno = 'CS114'
SNO SNAME AGE
--- ---------- ----
1 AARON 20
3 DOUG 20
4.3. sql
select s.*
from take t1, student s
where s.sno = t1.sno
and t1.cno = 'CS114'
and 'CS112' = any (select t2.cno
from take t2
where t1.sno = t2.sno
and t2.cno != 'CS114')
SNO SNAME AGE
--- ---------- ----
1 AARON 20
3 DOUG 20
4.4. DB2
4.5. Oracle
4.6. SQL Server
4.7. 視窗函數MIN OVER和MAX OVER
4.7.1. sql
select distinct sno, sname, age
from (
select s.sno, s.sname, s.age,
min(cno) over (partition by s.sno) as min_cno,
max(cno) over (partition by s.sno) as max_cno
from student s, take t
where s.sno = t.sno
and t.cno in ('CS114','CS112')
) x
where min_cno != max_cno
4.8. PostgreSQL
4.9. MySQL
4.10. 聚合函數MIN和MAX
4.10.1. sql
select s.sno, s.sname, s.age
from student s, take t
where s.sno = t.sno
and t.cno in ('CS114','CS112')
group by s.sno, s.sname, s.age
having min(t.cno) != max(t.cno)
4.11. IN列表確保只有選修CS112或CS114,或者同時兩門都選了的學生才會被保留下來
4.12. 如果一個學生沒有同時選修這兩門課程,那麼MIN(CNO)就會等於MAX(CNO),進而該學生會被排除在外
5. 問題8
5.1. 至少比其他兩位學生年齡大的學生
5.2. sql
select distinct s1.*
from student s1,
student s2,
student s3
where s1.age > s2.age
and s2.age > s3.age
SNO SNAME AGE
--- ---------- ----------
1 AARON 20
2 CHUCK 21
3 DOUG 20
5 STEVE 22
7 BRIAN 21
8 KAY 20
9 GILLIAN 20
10 CHAD 21
5.3. DB2
5.4. Oracle
5.5. SQL Server
5.6. 視窗函數DENSE_RANK
5.6.1. sql
select sno,sname,age
from (
select sno,sname,age,
dense_rank()over(order by age) as dr
from student
) x
where dr >= 3
5.7. PostgreSQL
5.8. MySQL
5.9. 聚合函數COUNT和關聯子查詢
5.9.1. sql
select s1.*
from student s1
where 2 <= ( select count(*)
from student s2
where s2.age <s1.age )