7.3. 选择列表

如前面的小节说明的那样,在SELECT命令中的表表达式通过组合表、视图、删除行、分组等构造了一个中介性的虚拟表。 这个表最后传递给选择列表处理。选择列表判断最终实际输出虚拟表的哪些字段

7.3.1. 选择列表项

最简单的选择列表是*,它输出表表达式生成的所有字段。否则,一个选择 列表是一个逗号分隔的值表达式的列表(和在Section 4.2里定义的一样)。 比如,它可能是一个字段名列表:

SELECT a, b, c FROM ...

字段名abc要么是在FROM子句里引用的表中字段的实际名字, 要么是Section 7.2.1.2里解释的别名。选择列表中的名字空间和WHERE子句中的 名字空间是一样的,除非你使用了分组,否则它和HAVING子句中的名字空间也一样。

如果多个表有重复的字段名,那么你还必须给出表名,例如:

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

当使用多个表时,给出表名还有助于引用该表的所有字段:

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

又见 Section 7.2.2

如果将值表达式用于选择列表,那么它在概念上向返回的表中增加了一个新的虚拟字段。 值表达式为结果中的每一行进行一次计算,计算之前用该行的数值替换任何表达式里 引用的字段。不过选择列表中的这个表达式并非一定要引用来自FROM子句中表表 达式里面的字段,比如,它也可以是任意常量算术表达式。

7.3.2. 字段标签

在选择列表中的项可以被指定用于后续的名字 处理,如在ORDER BY子句中使用, 或由客户端应用程序中显示。例如:

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

如果没有使用AS声明字段名,那么系统将赋予一个缺省值。对于简单的字段引用,它是该字段名。对于函数调用,它是该函数名。对于复杂表达式,系统会生成一个通用的名称。

只有当新列名与任何PostgreSQL关键字不匹配时AS关键字是可选的,但只有当新列名与任何PostgreSQL关键字不匹配时必须使用(参阅Appendix C)。 你可以给列名加上双引号来避免意外匹配关键字。 例如,VALUE是一个关键字,所以这样是不起作用的:

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

但这样可以:

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

为了防止和未来补充的关键字发生冲突,建议您要么写AS,要么为输出列名加双引号标记。

Note: 输出字段的命名和在FROM子句里的命名是不一样的(参阅节 Section 7.2.1.2)。这样就允许你对同一个字段命名两次,FROM子句里的名字将被选择列表使用, 而选择列表中新取的名字将被最终输出。

7.3.3. DISTINCT

在处理完选择列表之后,生成的表可以删除重复行。 直接在SELECT后面写上DISTINCT关键字即可:

SELECT DISTINCT select_list ...

(如果不用DISTINCT你可以用ALL声明保留所有行的缺省行为。)

显然,如果两行里至少有一个字段值不同,那么我们认为这两行是独立的。NULL在这里被认为是相同的。

另外,我们还可以用表达式来判断什么样的行可以认为是独立的:

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

这里的expression是一个值表达式,它为每一行计算。如果一组行计 算出的该表达式的值都相同,那么就认为这些行是重复的,并只输出第一行 。请注意这里的"第一行"是不可预料的,除非你在足够多的字段上对该查询进行了排序, 保证到达DISTINCT过滤器时行的顺序是唯一的(DISTINCT ON将在ORDER BY排序之后处理)。

DISTINCT ON子句不是SQL标准的一部分,有时候是一个糟糕的风格, 因为它的结果是不可判定的。如果有可选的GROUP BY和在FROM中的子查询可 以达到目的,那么我们可以避免使用这个构造,但是通常它是更方便的方法。