7.3. 选择列表#
如前一节所示,SELECT
命令中的表表达式通过可能组合表、视图、消除行、分组等方式构建一个中间虚拟表。此表最终传递给选择列表进行处理。选择列表确定中间表的哪些列实际输出。
7.3.1. 选择列表项#
最简单的选择列表是*
,它会输出表表达式产生的所有列。否则,选择列表是值表达式的逗号分隔列表(如第 4.2 节中所定义)。例如,它可以是列名列表
SELECT a, b, c FROM ...
列名a
、b
和c
要么是FROM
子句中引用的表的列的实际名称,要么是如第 7.2.1.2 节中所述赋予它们的别名。选择列表中可用的名称空间与WHERE
子句中的相同,除非使用分组,在这种情况下,它与HAVING
子句中的相同。
如果多个表具有同名的列,则还必须给出表名,如下所示
SELECT tbl1.a, tbl2.a, tbl1.b FROM ...
在使用多张表时,还可以要求获取特定表的所有列
SELECT tbl1.*, tbl2.a FROM ...
有关*table_name
*.*
符号的更多信息,请参见第 8.16.5 节。
如果在选择列表中使用了任意值表达式,则从概念上讲,它会向返回的表中添加一个新的虚拟列。对于每行结果,值表达式会评估一次,并用行的值替换任何列引用。但是,选择列表中的表达式不必引用FROM
子句的表表达式中的任何列;例如,它们可以是常量算术表达式。
7.3.2. 列标签#
选择列表中的条目可以分配名称以供后续处理,例如用于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 节)。可以将同一列重命名两次,但选择列表中分配的名称将是传递的名称。
7.3.3.DISTINCT
#
处理完选择列表后,结果表可以选择进行重复行消除。DISTINCT
关键字直接写在SELECT
之后以指定此内容
SELECT DISTINCT select_list ...
(可以使用关键字ALL
代替DISTINCT
来指定保留所有行的默认行为。)
显然,如果两行至少在一个列值上不同,则它们被认为是不同的。在此比较中,空值被视为相等。
或者,一个任意表达式可以确定哪些行被认为是不同的
SELECT DISTINCT ON (expression [, expression ...]) select_list ...
此处*expression
*是一个任意值表达式,它针对所有行进行评估。一组所有表达式都相等的行的被视为重复项,并且仅保留该组的第一行作为输出。请注意,除非对查询按足够多的列进行排序以保证到达DISTINCT
过滤器的行的唯一排序,否则一组的“第一行”是不可预测的。(DISTINCT ON
处理在ORDER BY
排序后发生。)
DISTINCT ON
子句不是 SQL 标准的一部分,有时由于其结果的潜在不确定性而被认为是不良风格。通过明智地使用GROUP BY
和FROM
中的子查询,可以避免这种构造,但它通常是最方便的替代方案。