2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本: devel
不再支持的版本: 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.3. SELECT 列表 #

如前一节所示,SELECT 命令中的表表达式通过可能组合表、视图、消除行、分组等来构造一个中间的虚拟表。这个表最终被传递给select list(SELECT 列表)进行处理。SELECT 列表决定了中间表的哪些实际上被输出。

7.3.1. SELECT 列表项 #

最简单的 SELECT 列表是 *,它会输出表表达式生成的所有列。否则,SELECT 列表是一个由值表达式(定义见 第 4.2 节)组成的逗号分隔列表。例如,它可以是一个列名列表

SELECT a, b, c FROM ...

列名 abc 要么是 FROM 子句中引用的表的列的实际名称,要么是如 第 7.2.1.2 节中所解释的为它们指定的别名。在 SELECT 列表中可用的命名空间与 WHERE 子句中的相同,除非使用了分组,在这种情况下,它与 HAVING 子句中的相同。

如果多个表具有同名的列,则还必须提供表名,例如:

SELECT tbl1.a, tbl2.a, tbl1.b FROM ...

在处理多个表时,要求获取特定表的所有列也可能很有用:

SELECT tbl1.*, tbl2.a FROM ...

有关 table_name.* 表示法的更多信息,请参阅 第 8.16.5 节

如果在 SELECT 列表中使用了任意值表达式,它会概念性地向返回的表中添加一个新的虚拟列。该值表达式会为每一结果行求值一次,并将该行的值替换掉任何列引用。但 SELECT 列表中的表达式不必引用 FROM 子句的表表达式中的任何列;它们可以是常量算术表达式,例如。

7.3.2. 列标签 #

SELECT 列表中的项可以被分配名称,以便后续处理,例如在 ORDER BY 子句中使用,或供客户端应用程序显示。例如:

SELECT a AS value, b + c AS sum FROM ...

如果未使用 AS 指定输出列名,则系统会分配一个默认列名。对于简单的列引用,这是被引用列的名称。对于函数调用,这是函数的名称。对于复杂的表达式,系统会生成一个通用名称。

AS 关键字通常是可选的,但在某些情况下,当期望的列名与PostgreSQL 关键字匹配时,您必须编写 AS 或对列名加双引号以避免歧义。(附录 C 显示了哪些关键字要求使用 AS 作为列标签。)例如,FROM 就是一个这样的关键字,所以这样做无效:

SELECT a from, b + c AS sum FROM ...

但以下任一方式都有效:

SELECT a AS from, b + c AS sum FROM ...
SELECT a "from", b + c AS sum FROM ...

为了最大程度地避免未来可能添加的关键字产生冲突,建议您始终使用 AS 或为输出列名加双引号。

注意

这里的输出列命名与 FROM 子句中的命名不同(参见 第 7.2.1.2 节)。可以对同一列重命名两次,但 SELECT 列表中指定的名称将是传递给后续处理的名称。

7.3.3. DISTINCT #

在 SELECT 列表处理完毕后,结果表可以选择性地进行重复行消除。DISTINCT 关键字直接写在 SELECT 之后,以指定此操作:

SELECT DISTINCT select_list ...

(可以使用 ALL 关键字代替 DISTINCT 来指定保留所有行的默认行为。)

显然,当两行在至少一个列值上存在差异时,它们被认为是不同的。在此比较中,NULL 值被认为是相等的。

或者,可以使用任意表达式来确定哪些行应被视为不同:

SELECT DISTINCT ON (expression [, expression ...]) select_list ...

在此,expression 是一个任意值表达式,它会为所有行求值。对于所有表达式都相等的行集,它们被视为重复项,并且该集合中的第一行才会被保留在输出中。请注意,一个集合的“第一行”是不可预测的,除非查询是在足够多的列上排序,以保证到达 DISTINCT 过滤器的行具有唯一的顺序。(DISTINCT ON 处理发生在 ORDER BY 排序之后。)

DISTINCT ON 子句不是 SQL 标准的一部分,有时被认为是不好的风格,因为它可能产生不确定的结果。通过谨慎使用 GROUP BYFROM 中的子查询,可以避免这种构造,但它通常是最方便的替代方案。

提交更正

如果您在文档中看到任何不正确、与您对特定功能的体验不符或需要进一步澄清的内容,请使用 此表单 来报告文档问题。