💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 7.3\. 选择列表 如前面的小节说明的那样,在`SELECT`命令中的表表达式通过组合表、 视图、删除行、分组等构造了一个中介性的虚拟表。这个表最后传递给_选择列表_处理。 选择列表判断最终实际输出虚拟表的哪些_字段_。 ## 7.3.1\. 选择列表项 最简单的选择列表是`*`,它输出表表达式生成的所有字段。 否则,一个选择列表是一个逗号分隔的值表达式的列表(和在[Section 4.2](#calibre_link-487) 里定义的一样)。比如,它可能是一个字段名列表: ``` SELECT a, b, c FROM ... ``` 字段名`a`, `b`,`c`要么是在`FROM` 子句里引用的表中字段的实际名字,要么是[Section 7.2.1.2](#calibre_link-488) 里解释的别名。选择列表中的名字空间和`WHERE`子句中的名字空间是一样的, 除非你使用了分组,否则它和`HAVING`子句中的名字空间也一样。 如果多个表有重复的字段名,那么你还必须给出表名字,例如: ``` SELECT tbl1.a, tbl2.a, tbl1.b FROM ... ``` 当使用多个表时,给出表名还有助于引用该表的所有字段: ``` SELECT tbl1.*, tbl2.a FROM ... ``` 又见[Section 7.2.2](#calibre_link-489)。 如果将值表达式用于选择列表,那么它在概念上向返回的表中增加了一个新的虚拟字段。 值表达式为结果中的每一行进行一次计算,计算之前用该行的数值替换任何表达式里引用的字段。 不过选择列表中的这个表达式并非一定要引用来自`FROM`子句中表表达式里面的字段, 比如,它也可以是任意常量算术表达式。 ## 7.3.2\. 字段标签 选择列表中的列表项可以赋予名字,以便于进一步的处理。 例如在`ORDER BY`子句中的使用或通过客户端应用程序显示。比如: ``` SELECT a AS value, b + c AS sum FROM ... ``` 如果没有使用`AS`声明字段名字,那么系统将赋予一个缺省值。 对于简单的字段引用,它是该字段的名字。对于函数调用,它是该函数的名字。 对于复杂表达式,系统会生成一个通用的名字。 只有当新列名与任何PostgreSQL 关键字不匹配时`AS`关键字是可选的(见[Appendix C](#calibre_link-126)), 您可以给列名加上双引号来避免意外匹配关键字。例如,`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](#calibre_link-488))。 这样就允许你对同一个字段命名两次,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` 中的子查询可以达到目的,那么我们可以避免使用这个构造,但是通常它是更方便的方法。