↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 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 已结束支持。 请参阅 当前版本手册.

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

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.

历史原文引用 (1)

此原始版本缺少部分引用目标。正文已标明这些引用,下列清单保留原始地址。

  • sql-select.html#SQL-ORDERBY-TITLE