↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1 / 7.0 / 6.5 / 6.4
历史版本PostgreSQL 7.1 已于 2006 年 4 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

SELECT

SELECT — 从表或视图中检索行

大纲

SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    * | expression [ AS output_name ] [, ...]
    [ FROM from_item [, ...] ]
    [ WHERE condition ]
    [ GROUP BY expression [, ...] ]
    [ HAVING condition [, ...] ]
    [ { UNION | INTERSECT | EXCEPT [ ALL ] } select ]
    [ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]
    [ FOR UPDATE [ OF tablename [, ...] ] ]
    [ 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_type from_item
    [ ON join_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_list

USING 列列表 ( a, b, ... ) 是 ON 条件 left_table.a = right_table.a AND left_table.b = right_table.b ... 的简写。

输出

Rows

由查询说明产生的完整行集合。

→ 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 子句

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 条件具有如下一般形式:

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 指定通过应用此子句导出的分组表:

GROUP BY expression [, ...]
    

GROUP BY 把在分组列上共享相同值的所有选中行压缩为单行。聚合函数(如果使用了的话)会在组成每个组的所有行上进行计算,为每个组产生一个单独的值(而没有 GROUP BY 时,聚合会产生一个在所有被选中的行上计算出的单一值)。当存在 GROUP BY 时,SELECT 输出表达式引用未分组的列是无效的,除非是在聚合函数内部,因为对一个未分组的列可能会有多个可能的返回值。

GROUP BY 项可以是输入列名、输出列(SELECT 表达式)的名称或序号,也可以是由输入列值构成的任意表达式。在有歧义时,GROUP BY 名称将被解释为输入列名而不是输出列名。

HAVING 子句

可选的 HAVING 条件具有如下一般形式:

HAVING boolean_expr
    

其中 boolean_expr 与为 WHERE 子句指定的相同。

HAVING 指定通过消除不满足 boolean_expr 的组行而导出的分组表。HAVING 与 WHERE 不同:WHERE 在应用 GROUP BY 之前过滤单独的行,而 HAVING 过滤 GROUP BY 创建的组行。

boolean_expr 中引用的每一列都应无歧义地引用一个分组列,除非该引用出现在聚合函数内。

ORDER BY 子句

ORDER BY expression [ ASC | DESC | USING operator ] [, ...]
    

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 >。

UNION 子句

table_query UNION [ ALL ] table_query
    [ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]
    [ 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。

INTERSECT 子句

table_query INTERSECT [ ALL ] table_query
    [ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]
    [ 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)。

EXCEPT 子句

table_query EXCEPT [ ALL ] table_query
    [ ORDER BY expression [ ASC | DESC | USING operator ] [, ...] ]
    [ 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 子句

    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

SELECT 子句

在 SQL92 标准中,可选的关键字 "AS" 只是无意义的噪音,可以省略而不影响含义。Postgres 解析器在重命名输出列时要求这个关键字,因为类型可扩展特性在此上下文中会导致解析歧义。不过 "AS" 在 FROM 项中是可选的。

DISTINCT ON 短语不是 SQL92 的一部分。LIMIT 和 OFFSET 也不是。

在 SQL92 中,ORDER BY 子句只能使用结果列名或编号,而 GROUP BY 子句只能使用输入列名。Postgres 扩展了这两个子句,也允许另一种选择(但在有歧义时使用标准的解释)。Postgres 还允许两个子句指定任意表达式。注意,表达式中出现的名称总是被当作输入列名,而不是结果列名。

UNION/INTERSECT/EXCEPT 子句

SQL92 的 UNION/INTERSECT/EXCEPT 语法允许一个附加的 CORRESPONDING BY 选项:

 
table_query UNION [ALL]
    [CORRESPONDING [BY (column [,...])]]
    table_query
     

Postgres 不支持 CORRESPONDING BY 子句。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。