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 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。