原文地址:http://mis.blogbus.com/logs/11754651.html
原來集合運算在刪選條件爲非唯一屬性時才顯的那麼重要
-------------------------------------
-- SQL集合運算——查詢的差集 --
-------------------------------------
--求沒有選擇課號爲‘c01’的學生學號
/*以下語句不正確,原因是cid不是獨立主鍵,並不能函數決定sid,
意味着選擇了'c01'的某一sid,可能會同時選擇非'c01'的其他cid,
因此,並不能通過僅排除'c01',而將所有的曾選擇過'c01'的該sid排除在外。
該查詢的目標範圍將比實際的大。
*/
select sid from learning
where cid<>'c01'
/*正確語句*/
select sid from learning
except (
select sid from learning where cid='c01'
)
--求沒有選擇課號爲‘c01’的學生的學號和課號
/*不正確。因爲sid與cid的同時存在於子查詢中,使得要減去的部分將比原來的小,
排除了該sid同時選擇其他cid而被排除的可能性。其結果範圍將比沒有cid的大。
*/
select sid,cid from learning
except (
select sid,cid from learning where cid='c01'
)
--正確:
select sid,cid from learning
where sid in (
select sid from learning
except (
select sid from learning where cid='c01'
)
)
-------------------------------------
-- SQL集合運算——查詢的交集 --
-------------------------------------
--求同時選了課號爲'c01'和'c02'的學生學號
/*以下語句不正確。其結果將是空值,因爲一個屬性在一個元組中只能有一個值,不會有兩個值。
select運行時只會一行一行地(逐個元組)進行,不會跨行進行比較。
*/
select sid from learning where cid='c01' and cid='c02'
/*以下語句正確:*/
select sid from learning where cid='c01'
intersect (
select sid from learning where cid='c02'
)
/*以下語句正確:通過自連接將cid的一個屬性,變成兩個名義屬性,再逐行進行比較:*/
select l1.sid from learning l1,learning l2
where l1.sid=l2.sid and l1.cid='c01' and l2.cid='c02'
--問題:求同時選了課號爲'c01'和‘c02’的學生學號和課號。
-------------------------------------
-- SQL集合運算——查詢的並集 --
-------------------------------------
--求計算機系學生的學號和選了'c03'課程且成績在分以上的學生學號
select sid from student where department='計算機系'
union (
select sid from learning
where cid='c03' and score>80
)
--分解分析,兩個子查詢自動將重複出現的記錄合併
select sid from student where department='計算機系'
select sid from learning
where cid='c03' and score>70