數據庫中的表(table)本質上就是由行(row)組成的集合。因此,PostgreSQL 同樣支持集合論中的集合操作,包括並集(UNION)、交集(INTERSECT)和差集(EXCEPT):
UNION
操作符用於將兩個查詢結果合併成一個結果集,返回出現在第一個查詢或者出現在第二個查詢中的數據;INTERSECT
操作符用於返回兩個查詢結果中的共同部分,即同時出現在第一個查詢結果和第二個查詢結果中的數據;EXCEPT
操作符用於返回出現在第一個查詢結果中,但不在第二個查詢結果中的數據。
這三個操作符的作用如下圖所示:
集合操作符要求參與運算的兩個查詢結果具有相同數量的列,以及對應列的類型必須匹配或兼容。
UNION
UNION
操作符用於將兩個查詢結果合併成一個結果集,返回出現在第一個查詢或者出現在第二個查詢中的數據:
SELECT column1, column2
FROM table1
UNION [DISTINCT | ALL]
SELECT col1, col2
FROM table2;
其中,DISTINCT
表示將合併後的結果集進行去重;ALL
表示保留結果集中的重複記錄;如果省略,默認爲DISTINCT
。例如:
select * from (values(1),(2)) t1(n)
union
select * from (values(1),(3)) t2(n);
n|
-|
1|
2|
3|
select * from (values(1),(2)) t1(n)
union all
select * from (values(1),(3)) t2(n);
n|
-|
1|
2|
1|
3|
第一個查詢結果中只有一個數字 1;第二個查詢結果中保留了重複的數字 1。
INTERSECT
INTERSECT操作符用於返回兩個查詢結果中的共同部分,即同時出現在第一個查詢結果和第二個查詢結果中的數據:
SELECT column1, column2
FROM table1
INTERSECT [DISTINCT | ALL]
SELECT col1, col2
FROM table2;
其中,DISTINCT
表示將合併後的結果集進行去重;ALL
表示保留結果集中的重複記錄;如果省略,默認爲DISTINCT
。例如:
select * from (values(1),(2)) t1(n)
intersect
select * from (values(1),(3)) t2(n);
n|
-|
1|
select * from (values(1),(1),(2)) t1(n)
intersect all
select * from (values(1),(3)) t2(n);
n|
-|
1|
select * from (values(1),(1),(2)) t1(n)
intersect all
select * from (values(1),(1),(3)) t2(n);
n|
-|
1|
1|
第一個查詢結果中只有一個數字 1;第二個查詢雖然使用了 ALL 選項,結果也只有一個1;第三個查詢結果中有兩個 1。
EXCEPT
EXCEPT操作符用於返回出現在第一個查詢結果中,但不在第二個查詢結果中的數據:
SELECT column1, column2
FROM table1
EXCEPT [DISTINCT | ALL]
SELECT col1, col2
FROM table2;
其中,DISTINCT
表示將合併後的結果集進行去重;ALL
表示保留結果集中的重複記錄;如果省略,默認爲DISTINCT
。例如:
select * from (values(1),(1),(2)) t1(n)
except
select * from (values(1),(3)) t2(n);
n|
-|
2|
select * from (values(1),(1),(2)) t1(n)
except all
select * from (values(1),(3)) t2(n);
n|
-|
1|
2|
第一個查詢結果中沒有數字 1;第二個查詢結果中保留了一個數字 1。
分組與排序
對於分組操作,集合操作符中的每個查詢都可以包含一個GROUP BY
,不過它們只針對各自進行分組;如果想要對最終結果進行分組,需要在外層嵌套一個 SELECT 語句:
select n, count(*) from (
select * from (values(1),(2)) t1(n)
union all
select * from (values(1),(3)) t2(n)) t
group by n;
n|count|
-|-----|
1| 2|
2| 1|
3| 1|
如果要對集合運算的數據進行排序,需要將ORDER BY
子句寫在最後;集合操作符中的第一個查詢中不能出現排序操作:
select * from (values(1),(2)) t1(n)
order by n
union all
select * from (values(1),(3)) t2(n);
SQL Error [42601]: ERROR: syntax error at or near "union"
Position: 50
select * from (values(1),(2)) t1(n)
union all
select * from (values(1),(3)) t2(n)
order by n;
n|
-|
1|
1|
2|
3|
集合操作優先級
PostgreSQL 支持同時使用多個集合操作符,此時我們需要注意它們的優先級:
SELECT column1, column2
FROM table1
UNION [DISTINCT | ALL]
SELECT col1, col2
FROM table2
INTERSECT [DISTINCT | ALL]
SELECT c1, c2
FROM table3;
多個集合操作符使用以下執行順序:
- 相同的集合操作符按照從左至右的順序執行;
INTERSECT
的優先級高於UNION
和EXCEPT
;- 使用括號可以修改集合操作的執行順序。
以下示例使用了兩個UNION
操作符,其中一個增加了 ALL 選項:
select * from (values(1)) t1(n)
union all
select * from (values(1)) t2(n)
union
select * from (values(1)) t3(n);
n|
-|
1|
查詢最終的結果只有一個數字 1,因爲最後的UNION
去除了重複的數據。
以下示例使用了兩個不同的集合操作符:
select * from (values(1)) t1(n)
union all
select * from (values(1)) t2(n)
intersect
select * from (values(1)) t3(n);
n|
-|
1|
1|
查詢最終的結果包含了兩個數字 1,因爲INTERSECT
先執行,最後的UNION ALL
保留了重複的數據。
我們最後看一個使用括號的示例:
(
select * from (values(1)) t1(n)
union all
select * from (values(1)) t2(n)
)
intersect
select * from (values(1)) t3(n);
n|
-|
1|
歡迎關注❤️、點贊👍、轉發📣