本文介紹SELECT相關的查詢語句。
文法
[ WITH with_query [, ...] ]
SELECT [ ALL | DISTINCT ] select_expr [, ...]
[ FROM from_item [, ...] ]
[ WHERE condition ]
[ GROUP BY [ ALL | DISTINCT ] grouping_element [, ...] ]
[ HAVING condition]
[ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ]
[ ORDER BY expression [ ASC | DESC ] [, ...] ]
[ LIMIT [ count | ALL ] ]
參數
from_item
:有以下兩種形式。table_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
from_item join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]
join_type
:表的連線類型。[ INNER ] JOIN LEFT [ OUTER ] JOIN RIGHT [ OUTER ] JOIN FULL [ OUTER ] JOIN
grouping_element
() expression
WITH從句
WITH
從句定義了一個命名好的關係以供在一個查詢裡面使用。 它可以扁平化巢狀查詢或者簡化子查詢。 例如,下面的查詢是等價的。
SELECT a, b
FROM (
SELECT a, MAX(b) AS b FROM t GROUP BY a
) AS x;
WITH x AS (SELECT a, MAX(b) AS b FROM t GROUP BY a)
SELECT a, b FROM x;
也同樣適用於多子查詢的情況。
WITH
t1 AS (SELECT a, MAX(b) AS b FROM x GROUP BY a),
t2 AS (SELECT a, AVG(d) AS d FROM y GROUP BY a)
SELECT t1.*, t2.*
FROM t1
JOIN t2 ON t1.a = t2.a;
另外,在WITH分句中定義的關係可以互相串連。
WITH
x AS (SELECT a FROM t),
y AS (SELECT a AS b FROM x),
z AS (SELECT b AS c FROM y)
SELECT c FROM z;
GROUP BY從句
GROUP BY
分句對SELECT
語句的輸出進行分組,分組是匹配值的資料行。一個簡單的GROUP BY
分句可以包含由輸入列組成的任何錶達式或者或列序號(從1開始)。
以下查詢是等價的。 他們都對nationkey
列進行分組, 第一個查詢使用列序號, 第二個查詢使用列名。
SELECT count(*), nationkey FROM customer GROUP BY 2;
SELECT count(*), nationkey FROM customer GROUP BY nationkey;
在查詢語句中沒有指定列名的情況下,GROUP BY
子句也可以將輸出進行分組。 例如,以下查詢使用列mktsegment
進行分組,統計出customer
表的行數。
SELECT count(*) FROM customer GROUP BY mktsegment;
_col0
-------
29968
30142
30189
29949
29752
(5 rows)
在SELECT
語句中使用GROUP BY
子句時,所有輸出的列要麼是彙總函式,要麼是GROUP BY
子句中的列。
HAVING從句
HAVING子句與彙總函式以及GROUP BY子句共同使用,用來控制選擇分組。HAVING子句去掉不滿足條件的分組。在分組和彙總計算完成後,HAVING對分組進行過濾。以下樣本查詢customer表,並進行分組,查出賬戶餘額大於指定值的記錄。
SELECT count(*), mktsegment, nationkey,
CAST(sum(acctbal) AS bigint) AS totalbal
FROM customer
GROUP BY mktsegment, nationkey
HAVING sum(acctbal) > 5700000
ORDER BY totalbal DESC;
_col0 | mktsegment | nationkey | totalbal
-------+------------+-----------+----------
1272 | AUTOMOBILE | 19 | 5856939
1253 | FURNITURE | 14 | 5794887
1248 | FURNITURE | 9 | 5784628
1243 | FURNITURE | 12 | 5757371
1231 | HOUSEHOLD | 3 | 5753216
1251 | MACHINERY | 2 | 5719140
1247 | FURNITURE | 8 | 5701952
(7 rows)
UNION|INTERSECT|EXCEPT從句
UNION、INTERSECT和EXCEPT都是全集合操作符。這些分句被用來組合多於一個查詢語句的結果,最終形成一個結果。
query UNION [ALL | DISTINCT] query
query INTERSECT query
query EXCEPT query
參數ALL或DISTINCT控制最終結果集包含哪些行。如果指定參數ALL,則包含全部行,即使行完全相同。如果指定參數DISTINCT,則合并結果集,結果集只有唯一不重複的行。如果不指定參數,執行時預設使用DISTINCT。
多個集合操作符會從做到有的被處理,除非順序通過括弧被顯示指定。另外,INTERSECT比EXCEPT and UNION
有更高的優先順序,意味著A UNION B INTERSECT C EXCEPT D
和這個運算式是相同的A UNION (B INTERSECT C) EXCEPT D
。
UNION
UNION把所有結果集兩個結果集合并起來。下面是一個最簡單的可能使用UNION分句的例子。它選擇了值13並且合并了第二個選擇的值42,把他們結合起來。
SELECT 13
UNION
SELECT 42;
_col0
-------
13
42
(2 rows)
INTERSECT
INTERSECT只返回那些同時在第一個和第二個查詢裡面都出現的行結合。下面的例子是一個最簡單的可能使用INTERSECT分句的例子。它選擇了值13和42並把他們和第二個查詢選擇的值13做合并。既然42值在第一個查詢的結果集中,它並不會被包含在最終的結果集裡面。
SELECT 13
INTERSECT
SELECT 13;
_col0
-------
13
(2 rows)
EXCEPT
EXCEPT返回那些行僅存在於第一個查詢結果集不在第二個查詢結果集中。下面是最簡單的使用EXCEPT分句的例子。它選擇了值42並把他們和第二個查詢選擇的值13做合并。既然13也同時存在於第二個查詢結果集中,它不會被包含在最終的結果集中。
SELECT 42
EXCEPT
SELECT 13;
_col0
-------
42
(2 rows)
ORDER BY Clause
ORDER BY分句被用來排序一個結果集通過一個或者多個輸出運算式。
ORDER BY expression [ ASC | DESC ] [, ...]
每個運算式由列名或列序號(從1開始)組成。ORDER BY
子句作為查詢的最後一步,在GROUP BY
和 HAVING
子句之後。
LIMIT Clause
LIMIT分句限制了最終結果集的行數。LIMIT ALL
和略去LIMIT分句的結果一樣。以下樣本為查詢一個大表,LIMIT子句限制它只輸出5行(因為查詢沒有ORDER BY,所以隨意返回幾行)。
SELECT orderdate FROM orders LIMIT 5;
o_orderdate
-------------
1996-04-14
1992-01-15
1995-02-01
1995-11-12
1992-04-26
(5 rows)
Joins
它允許合并來自多個關聯的資料。
交叉串連
SELECT *
FROM nation, region;
nation表包含了25行,region表包含了5行,所以結果兩個表最終產生了125行。
子查詢
一個子查詢是一個包含了查詢的運算式。子查詢當它引用子查詢之外的列時是相關的。邏輯上來說,子查詢會被它的外圍查詢逐行評估。被引用的列將因此是固定的在子查詢的評估過程中。
EXISTS
EXISTS斷言決定是否一個子查詢可以返回任何行。
SELECT name
FROM nation
WHERE EXISTS (SELECT * FROM region WHERE region.regionkey = nation.regionkey)
IN
IN斷言決定一個子查詢返回的值是否在一個被給定的結果集中。IN的結果依照對nulls的標準結果。子查詢必須產生僅僅一列。
SELECT name
FROM nation
WHERE regionkey IN (SELECT regionkey FROM region)
標量子查詢
標量子查詢是一個非關聯的子查詢,返回零或者1行資料。如果這個子查詢返回了多於一行的資料,那將是個錯誤。如果子查詢沒有返回任何行,則返回的結果是NULL
。
SELECT name
FROM nation
WHERE regionkey = (SELECT max(regionkey) FROM region)