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

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.0 已于 2005 年 5 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

SELECT

SELECT — 从表或视图中检索行

大纲

SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    expression [ AS name ] [, ...]
    [ INTO [ TEMPORARY | TEMP ] [ TABLE ] new_table ]
    [ FROM table [ alias ] [, ...] ]
    [ WHERE condition ]
    [ GROUP BY column [, ...] ]
    [ HAVING condition [, ...] ]
    [ { UNION [ ALL ] | INTERSECT | EXCEPT } select ]
    [ ORDER BY column [ ASC | DESC | USING operator ] [, ...] ]
    [ FOR UPDATE [ OF class_name [, ...] ] ]
    LIMIT { count | ALL } [ { OFFSET | , } start ]
  

输入

expression

表的列名或一个表达式。

name

用 AS 子句为列或表达式指定另一个名称。此名称主要用于为列提供一个便于显示的标签。它也可以用于在 ORDER BY 和 GROUP BY 子句中引用该列的值。但 name 不能用于 WHERE 或 HAVING 子句;应改写该表达式。

TEMPORARY
TEMP

如果指定了 TEMPORARY 或 TEMP,则该表是为此会话唯一创建的,并在会话退出时自动删除。

new_table

如果指定了 INTO TABLE 子句,查询结果将存储在一个具有指定名称的新表中。 目标表(new_table)会 自动创建,在此命令执行之前必须不存在。 更多信息请参阅 SELECT INTO。

注意

CREATE TABLE AS 语句同样会从一个 select 查询 创建一个新表。

table

FROM 子句引用的现有表的名称。

alias

前面表的替代名称。它用于简洁或消除单个表内连接的歧义。

condition

一个结果为真或假的布尔表达式。见 WHERE 子句。

column

表的列名。

select

一个除 ORDER BY 和 LIMIT 子句外具有所有特性的 select 语句。

输出

Rows

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

→ count

查询返回的行数。

描述

SELECT 将从一个或多个表返回行。选择的候选是满足 WHERE 条件的行;如果省略 WHERE,则所有行都是候选。 (See WHERE 子句.)

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 子句.)

UNION 操作符允许结果是所涉及查询返回的行的集合。 (See UNION 子句.)

INTERSECT 操作符给出两个查询共同的行。 (See INTERSECT 子句.)

EXCEPT 操作符给出第一个查询返回而第二个查询不返回的行。 (See EXCEPT 子句.)

FOR UPDATE 子句允许 SELECT 语句对选中的行执行排他锁定。

LIMIT 子句允许把查询产生的行的一个子集返回给用户。 (See LIMIT 子句.)

你必须对一个表拥有 SELECT 权限才能读取它的值(见 GRANT/REVOKE 语句)。

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 column [, ...]
    

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

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

HAVING 子句

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

HAVING cond_expr
    

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

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

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

ORDER BY 子句

ORDER BY column [ ASC | DESC ] [, ...]
    

column 既可以是结果列名,也可以是序号。

序号指结果列的(从左到右的)位置。这一特性使得可以基于没有合适名称的列 定义排序。 这永远不是绝对必要的,因为总是可以 用 AS 子句为结果列赋予一个名称,例如:

SELECT title, date_prod + 1 AS newlen FROM films ORDER BY newlen;
    

也可以按任意表达式 ORDER BY(对 SQL92 的扩展),包括不出现在 SELECT 结果列表中的字段。 因此下面的语句是合法的:

SELECT name FROM distributors ORDER BY code;
    

注意,如果 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 column [ ASC | DESC ] [, ...] ]
    

其中 table_query 指定不带 ORDER BY 或 LIMIT 子句的任何 select 表达式。

UNION 操作符允许结果是所涉及查询返回的行的集合。 表示 UNION 的直接操作数的两个 SELECT 必须 产生相同数量的列,并且对应的列必须是 兼容的数据类型。

默认情况下,UNION 的结果不包含任何重复行,除非指定了 ALL 子句。

同一 SELECT 语句中的多个 UNION 操作符从左到右求值。注意 ALL 关键字不是全局性的,只应用于当前这对表结果。

INTERSECT 子句

table_query INTERSECT table_query
    [ ORDER BY column [ ASC | DESC ] [, ...] ]
    

其中 table_query 指定不带 ORDER BY 或 LIMIT 子句的任何 select 表达式。

INTERSECT 操作符给出两个查询共同的行。 表示 INTERSECT 的直接操作数的两个 SELECT 必须 产生相同数量的列,并且对应的列必须是 兼容的数据类型。

同一 SELECT 语句中的多个 INTERSECT 操作符从左到右求值,除非圆括号另有指示。

EXCEPT 子句

table_query EXCEPT table_query
     [ ORDER BY column [ ASC | DESC ] [, ...] ]
    

其中 table_query 指定不带 ORDER BY 或 LIMIT 子句的任何 select 表达式。

EXCEPT 操作符给出第一个查询返回而第二个查询不返回的行。 表示 EXCEPT 的直接操作数的两个 SELECT 必须 产生相同数量的列,并且对应的列必须是 兼容的数据类型。

同一 SELECT 语句中的多个 EXCEPT 操作符从左到右求值,除非圆括号另有指示。

LIMIT 子句

    LIMIT { count | ALL } [ { OFFSET | , } start ]
    OFFSET start
    

其中 count 指定返回的最大行数,start 指定开始返回行之前要跳过的行数。

LIMIT 允许只取回由查询其余部分产生的行的一部分。如果给出了限制数,则返回不超过那么多的行。如果给出了偏移,则在开始返回行之前跳过那么多的行。

使用 LIMIT 时,最好使用把结果行约束为唯一顺序的 ORDER BY 子句。否则你会得到查询行的一个不可预测的子集——你可能要的是第十到第二十行,但是按什么顺序的第十到第二十行?除非指定了 ORDER BY,否则你不知道顺序。

从 Postgres 7.0 起,查询优化器在生成查询计划时会把 LIMIT 考虑在内,所以很可能根据 LIMIT 和 OFFSET 的不同取值得到不同的计划(产生不同的行顺序)。因此,使用不同的 LIMIT/OFFSET 值选择查询结果的不同子集会得到不一致的结果,除非用 ORDER BY 强制可预测的结果顺序。这不是缺陷;这是 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 distributors.* WHERE name = 'Westwood';

 did | name
-----+----------
 108 | Westward
  

SQL92

SELECT 子句

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

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

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

UNION 子句

SQL92 的 UNION 语法允许一个附加的 CORRESPONDING BY 子句:

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

Postgres 不支持 CORRESPONDING BY 子句。

提交更正

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