pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
SELECT — 从表或视图中检索行
SELECT [ ALL | DISTINCT [ ON (expression[, ...] ) ] ] * |expression[ ASoutput_name] [, ...] [ FROMfrom_item[, ...] ] [ WHEREcondition] [ GROUP BYexpression[, ...] ] [ HAVINGcondition[, ...] ] [ { UNION | INTERSECT | EXCEPT [ ALL ] }select] [ ORDER BYexpression[ ASC | DESC | USINGoperator] [, ...] ] [ FOR UPDATE [ OFtablename[, ...] ] ] [ LIMIT {count| ALL } [ { OFFSET | , }start]] 其中from_item可以是: [ ONLY ]table_name[ * ] [ [ AS ]alias[ (column_alias_list) ] ] | (select) [ AS ]alias[ (column_alias_list) ] |from_item[ NATURAL ]join_typefrom_item[ ONjoin_condition| USING (join_column_list) ]
expression表的列名或一个表达式。
output_name用 AS 子句为输出列指定另一个名称。此名称主要用于为列提供一个便于显示的标签。它也可以用于在 ORDER BY 和 GROUP BY 子句中引用该列的值。但 output_name 不能用于 WHERE 或 HAVING 子句;应改写该表达式。
from_item一个表引用、子 SELECT 或 JOIN 子句。细节见下文。
condition一个结果为真或假的布尔表达式。见下面的 WHERE 和 HAVING 子句描述。
select一个除 ORDER BY、FOR UPDATE 和 LIMIT 子句外具有所有特性的 select 语句(当 select 用圆括号括起时,甚至这些也可以使用)。
FROM 项可以包含:
table_name一个现有表或视图的名称。如果指定了 ONLY,则只扫描该表。如果未指定 ONLY,则扫描该表及其所有后代表(如果有)。* 可以附加到表名后面以指示要扫描后代表,但从 Postgres 7.1 起这是默认行为。(在 7.1 之前的版本中,ONLY 是默认行为。)
alias前面 table_name 的替代名称。别名用于简写或消除自连接(同一张表被扫描多次)中的歧义。如果写了别名,还可以写一个列别名列表来为该表的一列或多列提供替代名称。
select子 SELECT 可以出现在 FROM 子句中。它的行为就像其输出在此单条 SELECT 命令期间被创建为临时表一样。注意子 SELECT 必须用圆括号括起,并且必须为它提供别名。
join_type下列之一:[ INNER ] JOIN, LEFT [ OUTER ] JOIN, RIGHT [ OUTER ] JOIN, FULL [ OUTER ] JOIN, or CROSS JOIN. 对于 INNER 和 OUTER 连接类型,必须恰好出现 NATURAL、ON join_condition 或 USING ( join_column_list ) 之一。对于 CROSS JOIN,这些项都不能出现。
join_condition一个限定条件。它类似于 WHERE 条件,只是它只应用于在此 JOIN 子句中连接的两个 from_item。
join_column_listUSING 列列表 ( a, b, ... ) 是 ON 条件 left_table.a = right_table.a AND left_table.b = right_table.b ... 的简写。
由查询说明产生的完整行集合。
count查询返回的行数。
SELECT 将从一个或多个表返回行。选择的候选是满足 WHERE 条件的行;如果省略 WHERE,则所有行都是候选。(See WHERE 子句.)
实际上,返回的行并不直接是 FROM/WHERE/GROUP BY/HAVING 子句产生的行;输出行是通过对每个选中行计算 SELECT 输出表达式而形成的。* 可以作为所有选中行的列的简写在输出列表中写。还可以写 table_name.* 作为只来自该表的列的简写。
DISTINCT 将从结果中消除重复行。ALL(默认)将返回所有候选行,包括重复行。
DISTINCT ON 消除在所有指定表达式上匹配的行,只保留每组重复行中的第一行。DISTINCT ON 表达式使用与 ORDER BY 项相同的规则解释;见下文。注意,除非用 ORDER BY 确保希望的行排在前面,否则每组的“第一行”是不可预测的。例如,
SELECT DISTINCT ON (location) location, time, report
FROM weatherReports
ORDER BY location, time DESC;
它取回每个位置的最新天气报告。但如果我们没有用 ORDER BY 强制每个位置的时间值降序,我们就会得到每个位置一个不可预测时间的报告。
GROUP BY 子句允许用户把一个表划分为在一个或多个值上匹配的行组。(See GROUP BY 子句.)
HAVING 子句允许只选择满足指定条件的那些行组。(See HAVING 子句.)
ORDER BY 子句使返回的行按指定的顺序排序。如果没有给出 ORDER BY,行按系统认为产生成本最低的任何顺序返回。(See ORDER BY 子句.)
SELECT 查询可以用 UNION、INTERSECT 和 EXCEPT 操作符组合。必要时使用圆括号来确定这些操作符的顺序。
UNION 操作符计算所涉及查询返回的行的集合。除非指定 ALL,否则消除重复行。(See UNION 子句.)
INTERSECT 操作符计算两个查询共同的行。除非指定 ALL,否则消除重复行。(See INTERSECT 子句.)
EXCEPT 操作符计算第一个查询返回的行,但不返回第二个查询的行。除非指定 ALL,否则消除重复行。(See EXCEPT 子句.)
FOR UPDATE 子句允许 SELECT 语句对选中的行执行排他锁定。
LIMIT 子句允许把查询产生的行的一个子集返回给用户。(See LIMIT 子句.)
你必须对一个表拥有 SELECT 权限才能读取它的值(见 GRANT/REVOKE 语句)。
FROM 子句为 SELECT 指定一个或多个源表。如果指定多个源,结果在概念上是所有源中所有行的笛卡尔积——但通常会添加限定条件把返回的行限制为笛卡尔积的一个小子集。
当 FROM 项是一个简单表名时,它隐式地包括该表的子表(继承子女)的行。ONLY 将抑制来自该表子表的行。在 Postgres 7.1 之前,这是默认结果,添加子表是通过在表名后附加 * 完成的。这一旧行为可以通过命令 SET SQL_Inheritance TO OFF; 使用。
FROM 项也可以是用圆括号括起的子 SELECT(注意子 SELECT 必须有别名子句!)。这是一个极其方便的特性,因为它是在单个查询中获得多级分组、聚合或排序的唯一方式。
最后,FROM 项可以是 JOIN 子句,它组合两个更简单的 FROM 项。(必要时使用圆括号来确定嵌套顺序。)
CROSS JOIN 或 INNER JOIN 是简单的笛卡尔积,与在 FROM 顶层列出两个项所得到的相同。CROSS JOIN 等价于 INNER JOIN ON (TRUE),即没有行被限定移除。这些连接类型只是记法上的便利,因为它们没有做任何用普通 FROM 和 WHERE 做不到的事。
LEFT OUTER JOIN 返回限定笛卡尔积中的所有行(即通过其 ON 条件的所有组合行),再加上左表中每一个没有通过 ON 条件的右行的行的一个副本。这个左表行通过为右表列插入 NULL 扩展到被连接表的全宽度。注意,在决定哪些行有匹配时只考虑 JOIN 自己的 ON 或 USING 条件。外层的 ON 或 WHERE 条件在此之后应用。
相反,RIGHT OUTER JOIN 返回所有连接后的行,再加上每个未匹配右侧行对应的一行(左侧用空值扩展)。这只是一种记法上的便利,因为你可以通过交换左右表将其改写成 LEFT OUTER JOIN。
FULL OUTER JOIN 返回所有连接后的行,再加上每个未匹配的左侧行(右侧用空值扩展),以及每个未匹配的右侧行(左侧用空值扩展)。
对于除 CROSS JOIN 外的所有 JOIN 类型,必须恰好写下列之一:ON join_condition, USING ( join_column_list ), or NATURAL. ON 是最一般的情况:可以写涉及要连接的两个表的任何限定表达式。USING 列列表 ( a, b, ... ) 是 ON 条件 left_table.a = right_table.a AND left_table.b = right_table.b ... 的简写。另外,USING 隐含着每对等价列中只有一列会包含在 JOIN 输出中,而不是两列都包含。NATURAL 是一个提及两表中所有同名列的 USING 列表的简写。
可选的 WHERE 条件具有如下一般形式:
WHERE boolean_expr
boolean_expr 可以是任何求值为布尔值的表达式。在很多情况下,这个表达式会是:
expr cond_op expr
或
log_op expr
其中 cond_op 可以是 =、<、<=、>、>= 或 <> 之一,或像 ALL、ANY、IN、LIKE 这样的条件操作符,或本地定义的操作符,而 log_op 可以是 AND、OR、NOT 之一。SELECT 将忽略所有 WHERE 条件不返回 TRUE 的行。
GROUP BY 指定通过应用此子句导出的分组表:
GROUP BY expression [, ...]
GROUP BY 把在分组列上共享相同值的所有选中行压缩为单行。聚合函数(如果使用了的话)会在组成每个组的所有行上进行计算,为每个组产生一个单独的值(而没有 GROUP BY 时,聚合会产生一个在所有被选中的行上计算出的单一值)。当存在 GROUP BY 时,SELECT 输出表达式引用未分组的列是无效的,除非是在聚合函数内部,因为对一个未分组的列可能会有多个可能的返回值。
GROUP BY 项可以是输入列名、输出列(SELECT 表达式)的名称或序号,也可以是由输入列值构成的任意表达式。在有歧义时,GROUP BY 名称将被解释为输入列名而不是输出列名。
可选的 HAVING 条件具有如下一般形式:
HAVING boolean_expr
其中 boolean_expr 与为 WHERE 子句指定的相同。
HAVING 指定通过消除不满足 boolean_expr 的组行而导出的分组表。HAVING 与 WHERE 不同:WHERE 在应用 GROUP BY 之前过滤单独的行,而 HAVING 过滤 GROUP BY 创建的组行。
boolean_expr 中引用的每一列都应无歧义地引用一个分组列,除非该引用出现在聚合函数内。
ORDER BYexpression[ ASC | DESC | USINGoperator] [, ...]
ORDER BY 项可以是输出列(SELECT 表达式)的名称或序号,也可以是由输入列值构成的任意表达式。在有歧义时,ORDER BY 名称将被解释为输出列名。
序号指结果列的(从左到右的)位置。这一特性使得可以基于没有合适名称的列定义排序。这永远不是绝对必要的,因为总是可以用 AS 子句为结果列赋予一个名称,例如:
SELECT title, date_prod + 1 AS newlen FROM films ORDER BY newlen;
也可以按任意表达式 ORDER BY(对 SQL92 的扩展),包括不出现在 SELECT 结果列表中的字段。因此下面的语句是合法的:
SELECT name FROM distributors ORDER BY code;
这一特性的一个限制是:应用于 UNION、INTERSECT 或 EXCEPT 查询结果的 ORDER BY 子句只能指定输出列名或编号,不能指定表达式。
注意,如果 ORDER BY 项是一个既匹配结果列名又匹配输入列名的简单名称,ORDER BY 将把它解释为结果列名。这与 GROUP BY 在相同情况下所作的选择相反。这种不一致是 SQL92 标准规定的。
还可以在 ORDER BY 子句中的每个列名后面添加关键字 DESC(降序)或 ASC(升序)。如果未指定,默认为 ASC。或者,可以指定一个特定的排序操作符名称。ASC 等价于 USING < 而 DESC 等价于 USING >。
table_queryUNION [ ALL ]table_query[ ORDER BYexpression[ ASC | DESC | USINGoperator] [, ...] ] [ LIMIT {count| ALL } [ { OFFSET | , }start]]
其中 table_query 指定不带 ORDER BY、FOR UPDATE 或 LIMIT 子句的任何 select 表达式。(如果用圆括号括起,ORDER BY 和 LIMIT 可以附加到子表达式上。不带圆括号时,这些子句将被认为应用于 UNION 的结果,而不是它的右侧输入表达式。)
UNION 操作符计算所涉及查询返回的行的集合(集合并集)。表示 UNION 的直接操作数的两个 SELECT 必须产生相同数量的列,并且对应的列必须是兼容的数据类型。
UNION 的结果不包含任何重复行,除非指定了 ALL 选项。ALL 阻止消除重复行。
同一 SELECT 语句中的多个 UNION 操作符从左到右求值,除非圆括号另有指示。
目前,不能对 UNION 的结果或 UNION 的输入指定 FOR UPDATE。
table_queryINTERSECT [ ALL ]table_query[ ORDER BYexpression[ ASC | DESC | USINGoperator] [, ...] ] [ LIMIT {count| ALL } [ { OFFSET | , }start]]
其中 table_query 指定不带 ORDER BY、FOR UPDATE 或 LIMIT 子句的任何 select 表达式。
INTERSECT 类似于 UNION,只是它只产生在两个查询输出中都出现的行,而不是在任一输出中出现的行。
INTERSECT 的结果不包含任何重复行,除非指定了 ALL 选项。带 ALL 时,在 L 中有 m 个重复且在 R 中有 n 个重复的行将出现 min(m,n) 次。
同一 SELECT 语句中的多个 INTERSECT 操作符从左到右求值,除非圆括号另有指示。INTERSECT 比 UNION 绑定得更紧——也就是说,除非圆括号另有指定,A UNION B INTERSECT C 将被读作 A UNION (B INTERSECT C)。
table_queryEXCEPT [ ALL ]table_query[ ORDER BYexpression[ ASC | DESC | USINGoperator] [, ...] ] [ LIMIT {count| ALL } [ { OFFSET | , }start]]
其中 table_query 指定不带 ORDER BY、FOR UPDATE 或 LIMIT 子句的任何 select 表达式。
EXCEPT 类似于 UNION,只是它只产生在左查询输出中出现而在右查询输出中不出现的行。
EXCEPT 的结果不包含任何重复行,除非指定了 ALL 选项。带 ALL 时,在 L 中有 m 个重复且在 R 中有 n 个重复的行将出现 max(m-n,0) 次。
同一 SELECT 语句中的多个 EXCEPT 操作符从左到右求值,除非圆括号另有指示。EXCEPT 与 UNION 绑定在同一级别。
LIMIT { count | ALL } [ { OFFSET | , } start ]
OFFSET start
其中 count 指定返回的最大行数,start 指定开始返回行之前要跳过的行数。
LIMIT 允许只取回由查询其余部分产生的行的一部分。如果给出了限制数,则返回不超过那么多的行。如果给出了偏移,则在开始返回行之前跳过那么多的行。
使用 LIMIT 时,最好使用把结果行约束为唯一顺序的 ORDER BY 子句。否则你会得到查询行的一个不可预测的子集——你可能要的是第十到第二十行,但是按什么顺序的第十到第二十行?除非指定了 ORDER BY,否则你不知道顺序。
从 Postgres 7.0 起,查询优化器在生成查询计划时会把 LIMIT 考虑在内,所以很可能根据 LIMIT 和 OFFSET 的不同取值得到不同的计划(产生不同的行顺序)。因此,除非用 ORDER BY 强制可预测的结果顺序,用不同的 LIMIT/OFFSET 值选择查询结果的不同子集将得到不一致的结果。这不是缺陷;它是 SQL 不承诺以任何特定顺序给出查询结果这一事实的必然后果,除非用 ORDER BY 约束顺序。
把表 films 与表 distributors 连接:
SELECT f.title, f.did, d.name, f.date_prod, f.kind
FROM distributors d, films f
WHERE f.did = d.did
title | did | name | date_prod | kind
---------------------------+-----+------------------+------------+----------
The Third Man | 101 | British Lion | 1949-12-23 | Drama
The African Queen | 101 | British Lion | 1951-08-11 | Romantic
Une Femme est une Femme | 102 | Jean Luc Godard | 1961-03-12 | Romantic
Vertigo | 103 | Paramount | 1958-11-14 | Action
Becket | 103 | Paramount | 1964-02-03 | Drama
48 Hrs | 103 | Paramount | 1982-10-22 | Action
War and Peace | 104 | Mosfilm | 1967-02-12 | Drama
West Side Story | 105 | United Artists | 1961-01-03 | Musical
Bananas | 105 | United Artists | 1971-07-13 | Comedy
Yojimbo | 106 | Toho | 1961-06-16 | Drama
There's a Girl in my Soup | 107 | Columbia | 1970-06-11 | Comedy
Taxi Driver | 107 | Columbia | 1975-05-15 | Action
Absence of Malice | 107 | Columbia | 1981-11-15 | Action
Storia di una donna | 108 | Westward | 1970-08-15 | Romantic
The King and I | 109 | 20th Century Fox | 1956-08-11 | Musical
Das Boot | 110 | Bavaria Atelier | 1981-11-11 | Drama
Bed Knobs and Broomsticks | 111 | Walt Disney | | Musical
(17 rows)
对所有影片的 len 列求和并按 kind 分组:
SELECT kind, SUM(len) AS total FROM films GROUP BY kind; kind | total ----------+------- Action | 07:34 Comedy | 02:58 Drama | 14:28 Musical | 06:42 Romantic | 04:38 (5 rows)
对所有影片的 len 列求和,按 kind 分组,并显示少于 5 小时的组总计:
SELECT kind, SUM(len) AS total
FROM films
GROUP BY kind
HAVING SUM(len) < INTERVAL '5 hour';
kind | total
----------+-------
Comedy | 02:58
Romantic | 04:38
(2 rows)
下面两个例子是按照第二列(name)的内容对各个结果排序的相同方式:
SELECT * FROM distributors ORDER BY name; SELECT * FROM distributors ORDER BY 2; did | name -----+------------------ 109 | 20th Century Fox 110 | Bavaria Atelier 101 | British Lion 107 | Columbia 102 | Jean Luc Godard 113 | Luso films 104 | Mosfilm 103 | Paramount 106 | Toho 105 | United Artists 111 | Walt Disney 112 | Warner Bros. 108 | Westward (13 rows)
这个例子展示如何获得表 distributors 和 actors 的并集,把结果限制为每个表中以字母 W 开头的行。只需要不重复的行,所以省略了 ALL 关键字:
distributors: actors:
did | name id | name
-----+-------------- ----+----------------
108 | Westward 1 | Woody Allen
111 | Walt Disney 2 | Warren Beatty
112 | Warner Bros. 3 | Walter Matthau
... ...
SELECT distributors.name
FROM distributors
WHERE distributors.name LIKE 'W%'
UNION
SELECT actors.name
FROM actors
WHERE actors.name LIKE 'W%'
name
----------------
Walt Disney
Walter Matthau
Warner Bros.
Warren Beatty
Westward
Woody Allen
Postgres 允许在查询中省略 FROM 子句。此特性是从最初的 PostQuel 查询语言保留下来的。它有一个直接的用途:计算简单常量表达式的结果:
SELECT 2+2;
?column?
----------
4
一些其他 DBMS 做不到这一点,除非引入一个单行的哑表来从中做选择。一个不太明显的用法是缩写对一个或多个表的普通选择:
SELECT distributors.* WHERE name = 'Westward'; did | name -----+---------- 108 | Westward
这之所以可行,是因为对查询中引用但在 FROM 中未提及的每个表,都会添加一个隐式的 FROM 项。虽然这是一个方便的缩写,但很容易误用。例如,查询
SELECT distributors.* FROM distributors d;
很可能是笔误;用户最可能想要的是
SELECT d.* FROM distributors d;
而不是他实际会得到的无约束连接
SELECT distributors.* FROM distributors d, distributors distributors;
为了帮助检测这类错误,Postgres 7.1 及以后版本在查询同时使用了隐式 FROM 特性和显式 FROM 子句时将发出警告。
在 SQL92 标准中,可选的关键字 "AS" 只是无意义的噪音,可以省略而不影响含义。Postgres 解析器在重命名输出列时要求这个关键字,因为类型可扩展特性在此上下文中会导致解析歧义。不过 "AS" 在 FROM 项中是可选的。
DISTINCT ON 短语不是 SQL92 的一部分。LIMIT 和 OFFSET 也不是。
在 SQL92 中,ORDER BY 子句只能使用结果列名或编号,而 GROUP BY 子句只能使用输入列名。Postgres 扩展了这两个子句,也允许另一种选择(但在有歧义时使用标准的解释)。Postgres 还允许两个子句指定任意表达式。注意,表达式中出现的名称总是被当作输入列名,而不是结果列名。
SQL92 的 UNION/INTERSECT/EXCEPT 语法允许一个附加的 CORRESPONDING BY 选项:
table_queryUNION [ALL] [CORRESPONDING [BY (column[,...])]]table_query
Postgres 不支持 CORRESPONDING BY 子句。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。