SELECT
SELECT — 从表或视图中检索行
大纲
SELECT [ ALL | DISTINCT [ ON (expression[, ...] ) ] ]expression[ ASname] [, ...] [ INTO [ TEMPORARY | TEMP ] [ TABLE ]new_table] [ FROMtable[alias] [, ...] ] [ WHEREcondition] [ GROUP BYcolumn[, ...] ] [ HAVINGcondition[, ...] ] [ { UNION [ ALL ] | INTERSECT | EXCEPT }select] [ ORDER BYcolumn[ ASC | DESC | USINGoperator] [, ...] ] [ FOR UPDATE [ OFclass_name[, ...] ] ] LIMIT {count| ALL } [ { OFFSET | , }start]
输入
expression表的列名或一个表达式。
name用 AS 子句为列或表达式指定另一个名称。此名称主要用于为列提供一个便于显示的标签。它也可以用于在 ORDER BY 和 GROUP BY 子句中引用该列的值。但
name不能用于 WHERE 或 HAVING 子句;应改写该表达式。- TEMPORARY
TEMP 如果指定了 TEMPORARY 或 TEMP,则该表是为此会话唯一创建的,并在会话退出时自动删除。
new_table如果指定了 INTO TABLE 子句,查询结果将存储在一个具有指定名称的新表中。目标表(
new_table)会自动创建,在此命令执行之前必须不存在。更多信息请参阅SELECT INTO。注意
CREATE TABLE AS语句同样会从一个 select 查询创建一个新表。tableFROM 子句引用的现有表的名称。
alias前面表的替代名称。它用于简洁或消除单个表内连接的歧义。
condition一个结果为真或假的布尔表达式。见 WHERE 子句。
column表的列名。
select一个除 ORDER BY 和 LIMIT 子句外具有所有特性的 select 语句。
输出
- Rows
由查询说明产生的完整行集合。
- →
count 查询返回的行数。
描述
SELECT 将从一个或多个表返回行。选择的候选是满足 WHERE 条件的行;如果省略 WHERE,则所有行都是候选。(See WHERE 子句.)
DISTINCT 将从结果中消除重复行。ALL(默认)将返回所有候选行,包括重复行。
DISTINCT ON 消除在所有指定表达式上匹配的行,只保留每组重复行中的第一行。DISTINCT ON 表达式使用与
ORDER BY 项相同的规则解释;见下文。注意,除非用 ORDER BY 保证想要的行出现在最前,否则每个集合的"第一行"是不可预测的。例如,
SELECT DISTINCT ON (location) location, time, report
FROM weatherReports
ORDER BY location, time DESC;
它取回每个位置的最新天气报告。但如果我们没有用 ORDER BY 强制每个位置的时间值降序,就会得到每个位置年龄不可预测的报告。
GROUP BY 子句允许用户把一个表划分为在一个或多个值上匹配的行组。(See GROUP BY 子句.)
HAVING 子句允许只选择满足指定条件的那些行组。(See HAVING 子句.)
ORDER BY 子句使返回的行按指定的顺序排序。如果没有给出 ORDER BY,行按系统认为产生成本最低的任何顺序返回。(See ORDER BY 子句 [原文引用目标缺失] [查看原文章节].)
UNION 操作符允许结果是所涉及查询返回的行的集合。(See UNION 子句.)
INTERSECT 操作符给出两个查询共同的行。(See INTERSECT 子句.)
EXCEPT 操作符给出第一个查询返回而第二个查询不返回的行。(See EXCEPT 子句.)
FOR UPDATE 子句允许 SELECT 语句对选中的行执行排他锁定。
LIMIT 子句允许把查询产生的行的一个子集返回给用户。(See LIMIT 子句.)
你必须对一个表拥有 SELECT 权限才能读取它的值(见 GRANT/REVOKE 语句)。
WHERE 子句
可选的 WHERE 条件具有如下一般形式:
WHERE boolean_expr
boolean_expr
可以是任何求值为布尔值的表达式。在很多情况下,这个表达式会是
exprcond_opexpr
或
log_opexpr
其中 cond_op
可以是 =、<、<=、>、>= 或 <> 之一,或像 ALL、ANY、IN、LIKE 这样的条件操作符,或本地定义的操作符,而 log_op 可以是
AND、OR、NOT 之一。SELECT 将忽略所有 WHERE 条件不返回
TRUE 的行。
GROUP BY 子句
GROUP BY 指定通过应用此子句导出的分组表:
GROUP BY column [, ...]
GROUP BY 把在分组列上共享相同值的所有选中行压缩为单行。聚合函数(如果使用了的话)会在组成每个组的所有行上进行计算,为每个组产生一个单独的值(而没有 GROUP BY 时,聚合会产生一个在所有被选中的行上计算出的单一值)。当存在 GROUP BY 时,SELECT 输出表达式引用未分组的列是无效的,除非是在聚合函数内部,因为对一个未分组的列可能会有多个可能的返回值。
GROUP BY 中的项也可以是输出列(SELECT 表达式)的名称或序号,或者是由输入列值构成的任意表达式。在有歧义时,GROUP BY 名称将被解释为输入列名而不是输出列名。
HAVING 子句
可选的 HAVING 条件具有如下一般形式:
HAVING cond_expr
其中 cond_expr 与为 WHERE 子句指定的相同。
HAVING 指定通过消除不满足
cond_expr
的组行而导出的分组表。HAVING 与 WHERE 不同:WHERE 在应用 GROUP BY 之前过滤单独的行,而 HAVING 过滤 GROUP BY 创建的组行。
cond_expr 中引用的每一列都应无歧义地引用一个分组列,除非该引用出现在聚合函数内。
ORDER BY 子句
ORDER BY column [ ASC | DESC ] [, ...]
column 既可以是结果列名,也可以是序号。
序号指结果列的(从左到右的)位置。这一特性使得可以基于没有合适名称的列定义排序。这永远不是绝对必要的,因为总是可以用 AS 子句为结果列赋予一个名称,例如:
SELECT title, date_prod + 1 AS newlen FROM films ORDER BY newlen;
也可以按任意表达式 ORDER BY(对 SQL92 的扩展),包括不出现在 SELECT 结果列表中的字段。因此下面的语句是合法的:
SELECT name FROM distributors ORDER BY code;
注意,如果 ORDER BY 项是一个既匹配结果列名又匹配输入列名的简单名称,ORDER BY 将把它解释为结果列名。这与 GROUP BY 在相同情况下所作的选择相反。这种不一致是 SQL92 标准规定的。
还可以在 ORDER BY 子句中的每个列名后面添加关键字 DESC(降序)或 ASC(升序)。如果未指定,默认为 ASC。或者,可以指定一个特定的排序操作符名称。ASC 等价于 USING '<' 而 DESC 等价于 USING '>'。
UNION 子句
table_queryUNION [ ALL ]table_query[ ORDER BYcolumn[ ASC | DESC ] [, ...] ]
其中 table_query 指定不带 ORDER BY 或 LIMIT 子句的任何 select 表达式。
UNION 操作符允许结果是所涉及查询返回的行的集合。表示 UNION 的直接操作数的两个 SELECT 必须产生相同数量的列,并且对应的列必须是兼容的数据类型。
默认情况下,UNION 的结果不包含任何重复行,除非指定了 ALL 子句。
同一 SELECT 语句中的多个 UNION 操作符从左到右求值。注意 ALL 关键字不是全局性的,只应用于当前这对表结果。
INTERSECT 子句
table_queryINTERSECTtable_query[ ORDER BYcolumn[ ASC | DESC ] [, ...] ]
其中 table_query 指定不带 ORDER BY 或 LIMIT 子句的任何 select 表达式。
INTERSECT 操作符给出两个查询共同的行。表示 INTERSECT 的直接操作数的两个 SELECT 必须产生相同数量的列,并且对应的列必须是兼容的数据类型。
同一 SELECT 语句中的多个 INTERSECT 操作符从左到右求值,除非圆括号另有指示。
EXCEPT 子句
table_queryEXCEPTtable_query[ ORDER BYcolumn[ ASC | DESC ] [, ...] ]
其中 table_query 指定不带 ORDER BY 或 LIMIT 子句的任何 select 表达式。
EXCEPT 操作符给出第一个查询返回而第二个查询不返回的行。表示 EXCEPT 的直接操作数的两个 SELECT 必须产生相同数量的列,并且对应的列必须是兼容的数据类型。
同一 SELECT 语句中的多个 EXCEPT 操作符从左到右求值,除非圆括号另有指示。
LIMIT 子句
LIMIT { count | ALL } [ { OFFSET | , } start ]
OFFSET start
其中 count 指定返回的最大行数,start 指定开始返回行之前要跳过的行数。
LIMIT 允许只取回由查询其余部分产生的行的一部分。如果给出了限制数,则返回不超过那么多的行。如果给出了偏移,则在开始返回行之前跳过那么多的行。
使用 LIMIT 时,最好使用把结果行约束为唯一顺序的 ORDER BY 子句。否则你会得到查询行的一个不可预测的子集——你可能要的是第十到第二十行,但是按什么顺序的第十到第二十行?除非指定了 ORDER BY,否则你不知道顺序。
从 Postgres 7.0 起,查询优化器在生成查询计划时会把 LIMIT 考虑在内,所以很可能根据 LIMIT 和 OFFSET 的不同取值得到不同的计划(产生不同的行顺序)。因此,使用不同的 LIMIT/OFFSET 值选择查询结果的不同子集会得到不一致的结果,除非用 ORDER BY 强制可预测的结果顺序。这不是缺陷;这是 SQL 不承诺以任何特定顺序交付查询结果(除非用 ORDER BY 约束顺序)这一事实的固有后果。
用法
把表 films 与表 distributors 连接:
SELECT f.title, f.did, d.name, f.date_prod, f.kind
FROM distributors d, films f
WHERE f.did = d.did
title | did | name | date_prod | kind
---------------------------+-----+------------------+------------+----------
The Third Man | 101 | British Lion | 1949-12-23 | Drama
The African Queen | 101 | British Lion | 1951-08-11 | Romantic
Une Femme est une Femme | 102 | Jean Luc Godard | 1961-03-12 | Romantic
Vertigo | 103 | Paramount | 1958-11-14 | Action
Becket | 103 | Paramount | 1964-02-03 | Drama
48 Hrs | 103 | Paramount | 1982-10-22 | Action
War and Peace | 104 | Mosfilm | 1967-02-12 | Drama
West Side Story | 105 | United Artists | 1961-01-03 | Musical
Bananas | 105 | United Artists | 1971-07-13 | Comedy
Yojimbo | 106 | Toho | 1961-06-16 | Drama
There's a Girl in my Soup | 107 | Columbia | 1970-06-11 | Comedy
Taxi Driver | 107 | Columbia | 1975-05-15 | Action
Absence of Malice | 107 | Columbia | 1981-11-15 | Action
Storia di una donna | 108 | Westward | 1970-08-15 | Romantic
The King and I | 109 | 20th Century Fox | 1956-08-11 | Musical
Das Boot | 110 | Bavaria Atelier | 1981-11-11 | Drama
Bed Knobs and Broomsticks | 111 | Walt Disney | | Musical
(17 rows)
对所有影片的 len 列求和并按 kind 分组:
SELECT kind, SUM(len) AS total FROM films GROUP BY kind; kind | total ----------+------- Action | 07:34 Comedy | 02:58 Drama | 14:28 Musical | 06:42 Romantic | 04:38 (5 rows)
对所有影片的 len 列求和,按 kind 分组,并显示少于 5 小时的组总计:
SELECT kind, SUM(len) AS total
FROM films
GROUP BY kind
HAVING SUM(len) < INTERVAL '5 hour';
kind | total
----------+-------
Comedy | 02:58
Romantic | 04:38
(2 rows)
下面两个例子是按照第二列(name)的内容对各个结果排序的相同方式:
SELECT * FROM distributors ORDER BY name; SELECT * FROM distributors ORDER BY 2; did | name -----+------------------ 109 | 20th Century Fox 110 | Bavaria Atelier 101 | British Lion 107 | Columbia 102 | Jean Luc Godard 113 | Luso films 104 | Mosfilm 103 | Paramount 106 | Toho 105 | United Artists 111 | Walt Disney 112 | Warner Bros. 108 | Westward (13 rows)
这个例子展示如何获得表 distributors 和 actors 的并集,把结果限制为每个表中以字母 W 开头的行。只需要不重复的行,所以省略了 ALL 关键字:
distributors: actors:
did | name id | name
-----+-------------- ----+----------------
108 | Westward 1 | Woody Allen
111 | Walt Disney 2 | Warren Beatty
112 | Warner Bros. 3 | Walter Matthau
... ...
SELECT distributors.name
FROM distributors
WHERE distributors.name LIKE 'W%'
UNION
SELECT actors.name
FROM actors
WHERE actors.name LIKE 'W%'
name
----------------
Walt Disney
Walter Matthau
Warner Bros.
Warren Beatty
Westward
Woody Allen
兼容性
扩展
Postgres 允许在查询中省略 FROM 子句。此特性是从最初的 PostQuel 查询语言保留下来的:
SELECT distributors.* WHERE name = 'Westwood'; did | name -----+---------- 108 | Westward
SQL92
SELECT 子句
在 SQL92 标准中,可选的关键字 "AS" 只是无意义的噪音,可以省略而不影响含义。Postgres 解析器在重命名列时要求这个关键字,因为类型可扩展特性在此上下文中会导致解析歧义。
DISTINCT ON 短语不是 SQL92 的一部分。LIMIT 和 OFFSET 也不是。
在 SQL92 中,ORDER BY 子句只能使用结果列名或编号,而 GROUP BY 子句只能使用输入列名。Postgres 对这两个子句都做了扩展,允许也使用另一种选择(但在有歧义时采用标准的解释)。Postgres 还允许两个子句指定任意表达式。注意,表达式中出现的名称将总是被当作输入列名,而不是结果列名。
UNION 子句
SQL92 的 UNION 语法允许一个附加的 CORRESPONDING BY 子句:
table_queryUNION [ALL] [CORRESPONDING [BY (column[,...])]]table_query
Postgres 不支持 CORRESPONDING BY 子句。