7.3. 取得資料列表
如前一節所述,SELECT 指令中的資料示表表示式透過各種可能地組合資料表、view、消除資料列、分組等來建構中介的虛擬資料表。這個資料表最終會被傳遞給資料列表的處理。資料列表確認中介資料表的哪些欄位是實際上要輸出的。
7.3.1. 資料列表項目
最簡單的選擇列表是*,它表示資料表表示式產生的所有欄位。否則,資料列表是逗號分隔的參數表示式列表(如第 4.2 節中所定義的)。例如,它可能是欄位名稱的列表:
SELECT a, b, c FROM ...
欄位名稱 a、b 和 c 是 FROM 子句中資料表的欄位的實際名稱,或者是由第 7.2.1.2 節中所賦予它們的別名。資料列表中可用的命名空間與 WHERE 子句中的命名空間相同,除非是使用分組查詢,在這種情況下,它與 HAVING 子句中的相同。
如果多個資料表具有相同名稱的欄位,則還必須加上資料表的名稱,如下所示:
SELECT tbl1.a, tbl2.a, tbl1.b FROM ...
處理多個資料表時,查詢特定資料表的所有欄位也是可以的:
SELECT tbl1.*, tbl2.a FROM ...
有關 table_name.* 表示法的更多信息,請參閱第 8.16.5 節。
如果在資料列表中使用任意值表示式,則概念上是它將新的虛擬欄位加到回傳的資料表中。參數表示式對每個結果資料列計算一次,將該資料列的值替換為任何欄位引用。但是資料列表中的表示式不必引用 FROM 子句的資料表表示式中的任何欄位;例如,它們可以是常數算術表示式。
7.3.2. 欄位命名標籤
資料列表中的項目可以被分配用於後續處理的名稱,例如在 ORDER BY 子句中使用或由用戶端應用程序顯示。 例如:
SELECT a AS value, b + c AS sum FROM ...
如果沒有使用 AS 指定輸出欄位的名稱,系統將分配一個預設的欄位名稱。對於簡單欄位的引用,就是引用欄位的名稱。對於函數呼叫,就是函數的名稱。對於複雜的表示式,系統將會產成一個通用的名稱。
AS 關鍵字是選用的,但前提是新的欄位名稱不為任何PostgreSQL 關鍵字(請參閱附錄C)。為避免與關鍵字意外撞名,你可以對欄位名稱使用雙引號。例如,VALUE 是一個關鍵字,所以就不能這樣使用:
SELECT a value, b + c AS sum FROM ...
但這樣就可以了:
SELECT a "value", b + c AS sum FROM ...
為了防止未來可能增加的關鍵字,建議你習慣使用 AS 或總是在欄位名稱使用雙引號。
注意
這裡輸出欄位的命名與 FROM 子句中的命名不同(參閱第 7.2.1.2 節)。可以重新命名相同的欄位兩次,但在資料列表中分配的名稱是將要回傳的名稱。
7.3.3. DISTINCT
在處理了資料列表之後,結果資料表可以選擇性地消除重複的資料列。 DISTINCT 關鍵字在 SELECT 之後直接寫入以指定這個動作:
SELECT DISTINCT select_list ...
(如果不是 DISTINCT,而是關鍵字 ALL,可用於指定保留所有資料列的預設行為。)
顯然,如果至少有一個欄位值不同,則兩個資料列就會被認為是不同的。 在這個比較中,空值(null)被認為是相等的。
或者,使用表示式可以指定資料列如何被認為是不同的:
SELECT DISTINCT ON (expression [, expression ...]) select_list ...
這裡表示式是一個任意的運算表示式,對所有資料列進行求值運算。所有表示式相等的一組資料列被認為是重複的,並且只有該組的第一個資料列會被保留在輸出中。請注意,集合中的「第一行」是不可預知的,除非查詢按足夠的欄位進行排序,以保證進到 DISTINCT 過濾器的資料列是唯一排序。(在 ORDER BY 排序後才進行 DISTINCT ON 處理。)
DISTINCT ON 子句不是SQL標準的一部分,有時被認為是不好的樣式,因為其結果有潛在的不確定性。透過在 FROM 中智慧地使用 GROUP BY 和子查詢,可以避免這種結構,但這卻往往是最方便的選擇。