SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ] expression [ AS name ] [, ...] [ INTO [ TEMPORARY | TEMP ] [ TABLE ] new_table ] [ FROM table [ alias ] [, ...] ] [ WHERE condition ] [ GROUP BY column [, ...] ] [ HAVING condition [, ...] ] [ { UNION [ ALL ] | INTERSECT | EXCEPT } select ] [ ORDER BY column [ ASC | DESC | USING operator ] [, ...] ] [ FOR UPDATE [ OF class_name [, ...] ] ] LIMIT { count | ALL } [ { OFFSET | , } start ]
注意: CREATE TABLE AS 语句也将从选择查询中创建新表.
DISTINCT 将从选择出来的结果集中删除所有的重复的行。ALL (缺省)将返回所有侯选行,包括重复的行。
DISTINCT ON 删除匹配所有表达式的行,只保留每个重复集的第一行。注意这里每个重复集的"第一行"是不可预料的,除非我们用 ORDER BY 来保证我们希望的行最先出现。例如,
SELECT DISTINCT ON (location) location, time, report FROM weatherReports ORDER BY location, time DESC;检索出每个地区的最近的天气预报。但是如果我们没有使用 ORDER BY 来强制每个地区按时间值降续排列,我们得到的将是每个地区的不可预料的时间的报告。
检索出每个地区的最近的天气预报。但是如果我们没有使用 ORDER BY 来强制每个地区按时间值降续排列,我们得到的将是每个地区的不可预料的时间的报告。( GROUP BY 子句.)
HAVING 允许只选择那些满足声明条件的行组(参阅 HAVING 子句.)
ORDER BY 导致返回的行按照声明的顺序排列.如果没有给出 ORDER BY,输出的行的顺序将以系统认为开销最小的顺序产生.(参阅 ORDER BY 子句.)
UNION 操作符允许结果集是那些涉及到的查询所返回的行的集合。(参阅 UNION 子句。)
INTERSECT 给出两个查询公共的行。(参阅 INTERSECT 子句。)
EXCEPT 给出存在于第一个查询而不存在于第二个查询的行。(参阅 EXCEPT 子句。)
FOR UPDATE 子句允许 SELECT 语句对选出的行执行排他锁。
LIMIT 子句允许给用户返回一个查询生成的结果的子集。(参阅
LIMIT
子句。)
WHERE boolean_exprboolean_expr 可以包含任意个得出布尔值的表达式。通常表达式会是
expr cond_op expr或
log_op expr这里 cond_op 可以是下面之一:=,<,<=,>,>=,<> 或条件操作符象 ALL,ANY,IN,LIKE等,或者用户定义的操作符,而 log_op 可以为: AND,OR,NOT.SELECT 将忽略所有 WHERE 条件不为 TRUE 的行.
GROUP BY column [, ...]GROUP BY 将把所有在组合了的列上共享同样的值的行压缩成一行。如果存在聚集函数,这些聚集函数将计算每个组的所有行,并且为每个组计算一个独立的值(如果没有 GROUP BY,聚集函数对选出的所有行计算出一个数值)。存在 GROUP BY 时,除了在聚集函数里面,SELECT 输出表达式对任何非组合列的引用都是非法的,因为对一个非组合列会有多于一个可能的返回值。
一个在 GROUP BY 里面的条目还可以是输出列的名称或者序号(SELECT 表达式),或者是一个从输入列的数值形成的任意表达式.当存在语义模糊时,一个 GROUP BY 名称将被解释成一个输入列/字段名称而不是一个输出列/字段名称.
HAVING cond_expr这里 cond_expr 与为 WHERE 子句里声明的相同.
HAVING 子句声明一个从前面的子句的结果集中去除了一些不符合 cond_expr 组后分组的表.HAVING 与 WHERE 不同:WHERE 在应用 GROUP BY 之前过滤出单独的行,而 HAVING 过滤由 GROUP BY 创建的行.
在 cond_expr 里引用的每个列/字段应该清晰地指明一个组的列/字段,除非引用在一个聚集函数里。
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 等效于使用 '<' 而 DESC 等效于使用 '>'。
table_query UNION [ ALL ] table_query [ ORDER BY column [ ASC | DESC ] [, ...] ]这里 table_query 表明任何没有 ORDER BY 或者 LIMIT 子句的选择表达式.
UNION 操作符允许结果集是那些涉及到的查询所返回的结果的集合。两个做为 UNION 直接操作数的 SELECT 必须生成相同数目的字段,并且对应的字段必须有兼容的数据类型。
缺省地,UNION 的结果不包含任何重复的行,除非声明了 ALL 子句.
同一 SELECT 语句中的多个 UNION 操作符是从左向右计算的.注意 ALL 关键字不一定是全局的,只是应用在当前一对表的结果上.
table_query INTERSECT table_query [ ORDER BY column [ ASC | DESC ] [, ...] ]这里 table_query 声明任何没有 ORDER BY 或者 LIMIT 子句的选择表达式。
INTERSECT 给出两个查询公共的行。 两个做为 INTERSECT 直接操作数的 SELECT 的结果必须有相同数目的字段,并且对应的字段必须有兼容的数据类型。
除非用圆括号指明顺序,同一 SELECT 语句中的多个 INTERSECT 操作符是从左向右计算的。
table_query EXCEPT table_query [ ORDER BY column [ ASC | DESC ] [, ...] ]这里 table_query 声明任何没有 ORDER BY 或者 LIMIT 子句的选择表达式。
EXCEPT 给出存在于第一个查询而不存在于第二个查询的行。(参阅 EXCEPT 子句)。两个做为 EXCEPT 直接操作数的 SELECT 的结果必须有相同数目的字段,并且对应的字段必须有兼容的数据类型。
除非用圆括号指明顺序,同一 SELECT 语句中的多个 EXCEPT 操作符是从左向右计算的。
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 BYE 约束顺序,SQL 不保证查询生成的结果有任何特定的顺序。
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)统计用 kind 分组的所有电影和组的列/字段的 len (长度)的和:
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)统计所有电影(films),组的列/字段 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
SELECT distributors.* WHERE name = 'Westwood'; did | name -----+---------- 108 | Westward
DISTINCT ON 语法不是 SQL92 的标准。LIMIT 和 OFFSET 也不是。
在 SQL92 里,一个 ORDER BY 子句只可以使用在结果列名称或者序号上,而 GROUP BY 子句只能用于输入列/字段上.Postgres 把这两个子句都扩展为允许另一种选择(但是如果出现冲突则使用标准的解释).Postgres 还允许两个子句声明任意的表达式.请注意,在表达式里出现的名称将总是被当做输入列/字段的名称,而不是结果列/字段名称.