4.3. 选择列表

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

4.3.1. 选择列表项

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

SELECT a, b, c FROM ...

列名字ab,和c要么是在 FROM子句里引用的表中列的实际名字, 要么是象 Section 4.2.1.2 里解释的那样的 别名.在选择列表里的名字空间和在 WHERE 子句里的名字空间是一样的, 除非你使用了分组,这时候它和HAVING子句一样。

如果超过一个表有同样的列名字,那么你还必须给出表名字,象

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

(又见 Section 4.2.2).

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

4.3.2. 列标签

选择列表中的记录可以赋予名字用于进一步的处理. 这里的"进一步处理"是一个可选的排序声明和 客户端应用(比如,用于显示的列头).比如:

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

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

注意: 输出列的命名和在FROM子句里的命名是不一样的 (参阅 Section 4.2.1.2). 这个管道实际上允许你对同一个列命名两次,但是在选择列表中 选择的名字是要传递的名字.

4.3.3. DISTINCT

在处理完选择列表之后,生成的表可以删除重复行. 我们可以直接在 SELECT 后面写上 DISTINCT 关键字来实现这个目的:

SELECT DISTINCT select_list ...

(如果不用 DISTINCT 你可以用 ALL 选择保留所有行的缺省行为.)

显然,如果两行里至少有一个列有不同的值,那么我们认为它是 独立的.空值在这种考虑中认为是相同的.

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

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

这里 expression 是任意值表达式, 它为所有行计算.如果一个行集合里所有行计算出的该表达式的值 是一样的,那么我们认为它们是重复的并且因此只有第一行保留在 输出中.请注意这里的一个集合的"第一行"是不可 预料的,除非你在足够多的字段上对该查询排了序,保证到达 DISTINCT过滤器的行的顺序是唯一的.(DISTINCT ON处理是发生 在ORDER BY排序后面的.)

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