1. 程式人生 > >使用 UNION、INTERSECT 和 EXCEPT 對查詢結果執行集合運算

使用 UNION、INTERSECT 和 EXCEPT 對查詢結果執行集合運算

集合運算子和 NULL

集合運算子 UNION、EXCEPT 和 INTERSECT 處理 NULL 的方式與 NULL 在搜尋條件中時處理的方式不同。此差異是使用集合運算子的主要原因之一。

在比較行時,集合運算子將 NULL 值視為彼此相等。相反,在搜尋條件中將 NULL 與 NULL 進行比較時,結果是未知的(不為真)。

此差異的一個特別有用的結果是:query-1 EXCEPT ALL query-2 的結果集中的行數始終 是各個查詢的結果集中的行數之差。

以兩個表 T1 和 T2 為例,其中每個表都具有以下列:

col1 INT,
col2 CHAR(1)

表中的資料如下:

  • 表 T1。

    col1col2
    1 a
    2 b
    3 (NULL)
    3 (NULL)
    4 (NULL)
    4 (NULL)
  • 表 T2

    col1col2
    1 a
    2 x
    3 (NULL)

一個詢問同時出現在 T1 和 T2 中的行的查詢如下:

SELECT T1.col1, T1.col2
FROM T1 JOIN T2
ON T1.col1 = T2.col2
AND T1.col2 = T2.col2
T1.col1T1.col2
1 a

行 (3, NULL) 不出現在結果集中,因為 NULL 和 NULL 之間的比較不為真。相比之下,使用 INTERSECT 運算子處理該問題,則會包括一個有 NULL 的行:

SELECT col1, col2
FROM T1
INTERSECT
SELECT col1, col2
FROM T2
col1col2
1 a
3 (NULL)

以下查詢使用搜索條件列出 T1 中那些不出現在 T2 中的行:

SELECT col1, col2
FROM T1
WHERE col1 NOT IN (
    SELECT col1
    FROM t2
    WHERE t1.col2 = t2.col2 )
OR col2 NOT IN (
    SELECT col2
    FROM t2
    WHERE t1.col1 = t2.col1 )
col1col2
2 b
3 (NULL)
4 (NULL)
3 (NULL)
4 (NULL)

比較沒有排除 T1 中包含 NULL 的行。相比之下,使用 EXCEPT ALL 處理該問題會排除在這兩個表中都出現的包含 NULL 的行。在此情況下,會認為 T2 中的 (3, NULL) 行與 T1 中的 (3, NULL) 行相同。

SELECT col1, col2
FROM T1
EXCEPT ALL
SELECT col1, col2
FROM T2
col1 col2
2 b
3 (NULL)
4 (NULL)
4 (NULL)

EXCEPT 運算子仍然有更多的限制。它從 T1 中將兩個 (3, NULL) 行都去除,並將一個 (4, NULL) 行作為重複項排除。

SELECT col1, col2
FROM T1
EXCEPT
SELECT col1, col2
FROM T2
col1col2
2 b
4 (NULL)