在集合論中,集合A與B的差集(A-B)是由屬於集合A,但不屬於集合B的元素組成的集合。可以認為兩個集合的差A-B就是從A中減去B中也屬於A的元素。
在T-SQL中,集合之差是用EXCEPT集合運算實現的。EXCEPT運算對兩個輸入查詢的結果集進行操作,返回出現在第一個結果集中,但不出現在第二個結果集中的所有行。
EXCEPT DISTINCT 集合運算
EXCEPT 集合運算在邏輯上先刪除兩個輸入多集中的重復行(把多集轉變成集合),然后返回只在第一個集合中出現,在第二個集合中不出現所有行。換句話說,一個行能夠被返回,僅當這個行在第一個輸入的多集中至少出現一次,而且在第二個多集中沒有出現過。
注意:EXCEPT 運算與其他兩種集合運算不同,EXCEPT 是不對稱的。亦即,對於其他兩種集合運算,哪個輸入查詢放在前面,哪個輸入查詢放在后面是無關緊要的;但EXCEPT 集合運算就不是這樣了。
SELECT country FROM dbo.Employees
EXCEPT
SELECT country FROM dbo.Customers
EXCEPT 運算也可以用其他方法來實現。一種方法是使用外聯接,篩選出在聯接左邊出現而在右邊不出現的外部行。另一種方法是使用 NOT EXISTS 謂詞。
EXCEPT ALL集合運算
EXCEPT ALL 運算與EXCEPT運算非常類似,但它還考慮了每一行的出現次數。假設行R在第一個多集中出現了x次,在第二個多集中出現y次,且x>y,則在Query1 EXCEPT ALL Query2中,R出現 x-y次。換句話說,如果一個行在第一個多集中出現了多次,EXCEPT ALL 邏輯上只返回它在第二個多集中沒有相應出現過的那些行。雖然 SQL Server 沒有提供內建的EXCEPT ALL 運算,但用與INTERSECT ALL的解決方案類似的方法,也可以為EXCEPT ALL 提供替代的解決方案。也就是為每個輸入查詢增加一個ROW_Number計算,算出每行是第幾次出現,再對兩個輸入集應用EXCEPT 運算。這樣就只返回出現次數找不到匹配的行。
SELECT ROW_NUMBER() over(partition by country,region order by (SELECT 0)) as rownum,country
FROM dbo.Employees
EXCEPT
SELECT ROW_NUMBER() over(PARTITION BY country,region order by (SELECT 0)),country
FROM dbo.Customers