pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
SELECT — 从表或视图中检索行
SELECT [ ALL | DISTINCT [ ON (expression[, ...] ) ] ] * |expression[ ASoutput_name] [, ...] [ FROMfrom_item[, ...] ] [ WHEREcondition] [ GROUP BYexpression[, ...] ] [ HAVINGcondition[, ...] ] [ { UNION | INTERSECT | EXCEPT } [ ALL ]select] [ ORDER BYexpression[ ASC | DESC | USINGoperator] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT {count| ALL } ] [ OFFSETstart] [ FOR { UPDATE | SHARE } [ OFtable_name[, ...] ] [ NOWAIT ] ] wherefrom_itemcan be one of: [ ONLY ]table_name[ * ] [ [ AS ]alias[ (column_alias[, ...] ) ] ] (select) [ AS ]alias[ (column_alias[, ...] ) ]function_name( [argument[, ...] ] ) [ AS ]alias[ (column_alias[, ...] |column_definition[, ...] ) ]function_name( [argument[, ...] ] ) AS (column_definition[, ...] )from_item[ NATURAL ]join_typefrom_item[ ONjoin_condition| USING (join_column[, ...] ) ]
SELECT从零个或更多表中检索行。SELECT的总体处理如下:
所有FROM列表中的元素都会被计算。 (FROM列表中的每个元素都是一个真实或虚拟表。) 如果在FROM列表中指定了多个元素,则它们会被交叉连接在一起。 (参见下面的FROM Clause。)
如果指定了WHERE子句,则不满足条件的所有行将从输出中删除。 (请参见下面的WHERE Clause。)
如果指定了GROUP BY子句, 或者存在聚合函数调用, 输出将被组合成在一个或多个值上匹配的行组, 并计算聚合函数的结果。 如果存在HAVING子句, 它将消除不满足给定条件的组。(参见 GROUP BY Clause和 HAVING Clause。)
实际输出行是使用每个选定行或行组的SELECT输出表达式计算的。 (参见下面的SELECT List。)
使用操作符UNION、INTERSECT和EXCEPT,可以把多条SELECT语句的输出合并成一个结果集。UNION操作符返回在一个或两个结果集中的所有行。INTERSECT操作符返回严格同时在两个结果集中的所有行。EXCEPT操作符返回在第一个结果集中但不在第二个结果集中的行。在所有这三种情况下,除非指定了ALL,否则重复行都会被消除。(参见下面的 UNION Clause、INTERSECT Clause和 EXCEPT Clause。)
如果指定了ORDER BY子句,则返回的行按指定顺序排序。 如果没有给出ORDER BY,则按系统认为最快的顺序返回行。 (参见下面的ORDER BY Clause。)
DISTINCT消除结果中的重复行。 DISTINCT ON会消除在所有指定表达式上匹配的行,只保留每组中的第一行。 ALL(默认)将返回所有候选行,包括重复行。 (参见下面的DISTINCT Clause。)
如果指定了LIMIT或OFFSET子句, SELECT语句只返回结果行的子集。(参见下面的LIMIT Clause。)
如果指定了 FOR UPDATE 或 FOR SHARE 子句,SELECT 语句将选定的行锁定,防止并发更新。 (See FOR UPDATE/FOR SHARE 子句 below.)
你必须在一个表上拥有SELECT权限才能读取它的值。使用FOR UPDATE或FOR SHARE还要求UPDATE权限。
FROM ClauseFROM 子句为 SELECT 指定一个或更多源表。如果指定了多个源表,结果将是所有源表的笛卡尔积(交叉连接)。但通常会增加限定条件,把返回的行限制为该笛卡尔积的一个小子集。
该 FROM 子句可以包含以下元素:
table_name要扫描的现有表或视图的名称(可选模式限定符)。如果指定了ONLY,则只扫描该表。如果未指定ONLY,则扫描该表及其所有后代表(如果有)。可以在表名后附加*来指示要扫描后代表,但在当前版本中,这是默认行为。(在 7.1 之前的版本中,ONLY是默认行为。)可以通过更改sql_inheritance配置选项来修改默认行为。
alias包含该别名的FROM项的替代名称。别名可用于简写, 或者消除自连接(同一张表被扫描多次)中的歧义。提供别名后,它会 完全隐藏表或函数的实际名称;例如给定FROM foo AS f, SELECT的其余部分必须把这个FROM 项写成f而不是foo。如果写了别名, 还可以写列别名列表,为该表的一个或多个列提供替代名称。
select子SELECT可以出现在FROM子句中, 它的作用就像在这个SELECT命令的执行期间创建了一个 临时表。注意,子SELECT必须用圆括号括起来,并且 必须为其提供别名。
function_name函数调用可以出现在FROM子句中。(这对于返回结果集的函数尤其有用,但任何函数都可以使用。)其效果就像在这条SELECT命令执行期间,将函数的输出创建成了一张临时表。也可以使用别名。如果写了别名,还可以写一个列别名列表,为函数复合返回类型中的一个或多个属性提供替代名称。如果函数被定义为返回record数据类型,则必须给出别名或关键字AS,后面跟一个如下形式的列定义列表:( 。列定义列表必须与函数实际返回的列数和类型相匹配。column_name data_type [, ... ] )
join_type以下之一:
[ INNER ] JOIN
LEFT [ OUTER ] JOIN
RIGHT [ OUTER ] JOIN
FULL [ OUTER ] JOIN
CROSS JOIN
对于INNER和OUTER连接类型,必须指定一个连接条件,即NATURAL、ON 或join_conditionUSING (三者中恰好之一。其含义见下文。对于join_column [, ...])CROSS JOIN,这些子句都不能出现。
JOIN 子句组合两个 FROM 项。如有必要可用圆括号确定嵌套的顺序。在没有圆括号时,JOIN 从左到右嵌套。在任何情况下,JOIN 的结合都比分隔 FROM 项的逗号更紧。
CROSS JOIN和INNER JOIN产生简单的笛卡尔积,与在FROM顶层列出这两个表得到的结果相同,但会受到连接条件(如果有)的限制。CROSS JOIN等价于INNER JOIN ON (TRUE),也就是说,没有行会被条件过滤掉。这些连接类型只是提供了一种方便的记法,因为它们所做的一切都可以用普通的FROM和WHERE完成。
LEFT OUTER JOIN返回已限定笛卡尔积中的所有行(即,通过其连接条件的所有组合行),外加左侧表中每一行的一个副本;对于这些行,不存在通过连接条件的右侧行。这样的左侧行会通过在右侧列中插入空值而扩展到连接表的完整宽度。注意,在决定哪些行有匹配项时,只考虑JOIN子句自身的条件;外层条件是在之后应用的。
相反,RIGHT OUTER JOIN返回所有连接后的行,再加上每个未匹配右侧行对应的一行 (左侧用空值扩展)。这只是一种记法上的便利,因为你可以通过交换左右表 将其改写成LEFT OUTER JOIN。
FULL OUTER JOIN返回所有连接后的行,再加上每个未匹配的左侧行(右侧用空值扩展),以及每个未匹配的右侧行(左侧用空值扩展)。
ON join_conditionjoin_condition 是一个表达式,其结果类型为 boolean(类似于 WHERE 子句),用于指定连接中哪些行被视为匹配。
USING ( join_column [, ...] )一个形如USING ( a, b, ... )的子句是ON left_table.a = right_table.a AND left_table.b = right_table.b ...的简写。此外, USING意味着只有每对等价列中的一个会包含在连接输出中,而不是两者都包含。
NATURALNATURAL 是一个简写,表示一个列出两个表中所有同名列的 USING 列表。
WHERE Clause可选的WHERE子句的形式
WHERE condition
其中condition 是任一计算得到boolean类型结果的表达式。任何不满足 这个条件的行都会从输出中被消除。如果用一行的实际值替换其中的 变量引用后,该表达式返回真,则该行符合条件。
GROUP BY Clause可选的 GROUP BY 子句的一般形式为
GROUP BY expression [, ...]
GROUP BY会把所有在分组表达式上具有相同值的已选中 行压缩成单独一行。expression可以是输入列名、输出列 (SELECT列表项)的名称或序号或者由输入列 值构成的任意表达式。在出现歧义时,GROUP BY名称 将被解释为输入列名而不是输出列名。
聚合函数(如果使用了的话)会在组成每个组的所有行上进行计算,为每个组产生一个单独的值(而没有GROUP BY时,聚合会产生一个在所有被选中的行上计算出的单一值)。当存在GROUP BY时,SELECT列表表达式引用未分组的列是无效的,除非是在聚合函数内部,因为对一个未分组的列可能会有多个可能的返回值。
HAVING Clause可选的HAVING子句的形式
HAVING condition
其中condition与 WHERE子句中指定的条件相同。
HAVING消除不满足该条件的分组行。 HAVING与WHERE不同: WHERE会在应用GROUP BY之前过滤个体行,而HAVING过滤由 GROUP BY创建的分组行。 condition中引用 的每一列都必须无歧义地引用某个分组列,除非该引用出现在聚合 函数中,或者该非分组列函数依赖于分组列。
即使没有GROUP BY子句,HAVING 的存在也会把一个查询转变成一个分组查询。这和查询中包含聚合函数但没有 GROUP BY子句时的情况相同。所有被选择的行都被认为是一个 单一分组,并且SELECT列表和 HAVING子句只能从聚合函数内部引用表列。如果该 HAVING条件为真,这样的查询将输出单独一行; 否则不返回行。
SELECT ListSELECT列表(位于关键词 SELECT和FROM之间)指定构成 SELECT语句输出行的表达式。这些表达式 可以(并且通常确实会)引用FROM子句中计算得到的列。使用AS 子句可以为输出列指定另一个名称。这个名称主要用于给要显示的列做标记。它也可以用来在output_nameORDER BY和GROUP BY子句中引用该列的值,但不能用在WHERE或HAVING子句中;在那里必须写出表达式。
可以在输出列表中写*来取代表达式,它是被选中 行的所有列的一种简写方式。还可以写 ,它 是只来自那个表的所有列的简写形式。table_name.*
UNION ClauseUNION 子句的一般形式如下:
select_statementUNION [ ALL ]select_statement
select_statement 是不带 ORDER BY、LIMIT、FOR UPDATE 或 FOR SHARE 子句的任意 SELECT 语句。 (如果ORDER BY和LIMIT所附属的子表达式被圆括号括起,则它们可以附加到该子表达式上。不带圆括号时,这些子句会被认为适用于UNION的结果,而不是它的右手输入表达式。)
UNION操作符计算相关 SELECT语句所返回的行的并集。如果一行 至少出现在两个结果集中的一个内,它就会在并集中。作为 UNION两个操作数的 SELECT语句必须产生相同数量的列并且 对应位置上的列必须具有兼容的数据类型。
UNION的结果不包含任何重复行,除非指定了ALL选项。ALL阻止消除重复行。(因此,UNION ALL通常明显快于UNION;能用ALL时就用它。)
除非用圆括号指定计算顺序, 同一个SELECT语句中的多个 UNION操作符会从左至右计算。
当前,FOR UPDATE 和 FOR SHARE 不能为 UNION 的结果或 UNION 的任何输入指定。
INTERSECT ClauseINTERSECT 子句的一般形式如下:
select_statementINTERSECT [ ALL ]select_statement
select_statement 是不带 ORDER BY、LIMIT、FOR UPDATE 或 FOR SHARE 子句的任意 SELECT 语句。
INTERSECT操作符计算相关 SELECT语句返回的行的交集。如果 一行同时出现在两个结果集中,它就在交集中。
INTERSECT的结果不包含任何重复行,除非指定了ALL选项。 带ALL时,在左表中有m个重复、在右表中有n个重复的行将在结果集中出现 min(m,n) 次。
除非用圆括号指定计算顺序, 同一个SELECT语句中的多个 INTERSECT操作符会从左至右计算。 INTERSECT的优先级比 UNION更高。也就是说, A UNION B INTERSECT C将被读成A UNION (B INTERSECT C)。
当前,FOR UPDATE 和 FOR SHARE 不能为 INTERSECT 的结果或 INTERSECT 的任何输入指定。
EXCEPT ClauseEXCEPT 子句的一般形式如下:
select_statementEXCEPT [ ALL ]select_statement
select_statement 是不带 ORDER BY、LIMIT、FOR UPDATE 或 FOR SHARE 子句的任意 SELECT 语句。
EXCEPT操作符计算位于左侧 SELECT语句的结果中但不在右侧语句结果中的行集合。
EXCEPT的结果不包含任何重复行,除非指定了ALL选项。 带ALL时,在左表中有m个重复、在右表中有n个重复的行将在结果集中出现 max(m-n,0) 次。
除非用圆括号指定计算顺序, 同一个SELECT语句中的多个 EXCEPT操作符会从左至右计算。 EXCEPT的优先级与 UNION相同。
当前,FOR UPDATE 和 FOR SHARE 不能为 EXCEPT 的结果或 EXCEPT 的任何输入指定。
ORDER BY Clause可选的ORDER BY子句的形式如下:
ORDER BYexpression[ ASC | DESC | USINGoperator] [ NULLS { FIRST | LAST } ] [, ...]
ORDER BY子句导致结果行被按照指定的表达式排序。 如果两行按照最左边的表达式是相等的,则会根据下一个表达式比较它们, 依次类推。如果按照所有指定的表达式它们都是相等的,则它们被返回的 顺序取决于实现。
每一个expression 可以是输出列(SELECT列表项)的名称或 者序号,它也可以是由输入列值构成的任意表达式。
序号指的是输出列的顺序(从左至右)位置。这种特性可以为不具有唯一 名称的列定义一个顺序。这不是绝对必要的,因为总是可以使用 AS子句为输出列赋予一个名称。
也可以在ORDER BY子句中使用任意表达式,包括没 有出现在SELECT输出列表中的列。因此, 下面的语句是合法的:
SELECT name FROM distributors ORDER BY code;
这种特性的一个限制是一个应用在UNION、 INTERSECT或EXCEPT子句结果上的 ORDER BY只能指定输出列名称或序号,但不能指定表达式。
如果一个ORDER BY表达式是一个既匹配输出列名称又匹配 输入列名称的简单名称,ORDER BY将把它解读成输出列名 称。这与在同样情况下GROUP BY会做出的选择相反。这种 不一致是为了与 SQL 标准兼容。
可以在ORDER BY子句中任一表达式之后附加关键字 ASC(升序)或DESC(降序)。如果没有指定, ASC被假定为默认值。或者,可以在USING 子句中指定一个特定的排序操作符名称。一个排序操作符必须是某个 B-树操作符族的小于或者大于成员。ASC通常等价于 USING <而DESC通常等价于 USING >(但是一种用户定义数据类型的创建者可以 准确地定义默认排序顺序是什么,并且它可能会对应于其他名称的操作符)。
空值的排序高于任何其他值。换句话说,在升序排序时,空值排在最后; 在降序排序时,空值排在最前。
字符串数据按照数据库集簇初始化时建立的区域相关排序顺序来排序。
DISTINCT Clause如果指定了DISTINCT,所有重复的行会被从结果 集中移除(为每一组重复的行保留一行)。ALL则 指定相反的行为:所有行都会被保留,这也是默认情况。
DISTINCT ON ( 只保留在给定表达式上计算相等的行集合中的第一行。 expression [, ...] )DISTINCT ON表达式使用和 ORDER BY相同的规则(见上文)解释。注意,除非用 ORDER BY来确保所期望的行出现在第一位,每一个集 合的“第一行”是不可预测的。例如:
SELECT DISTINCT ON (location) location, time, report
FROM weather_reports
ORDER BY location, time DESC;
为每个地点检索最近的天气报告。但是如果我们不使用 ORDER BY来强制对每个地点的时间值进行降序排序, 我们为每个地点得到的报告的时间可能是无法预测的。
DISTINCT ON表达式必须匹配最左边的 ORDER BY表达式。ORDER BY子句通常 将包含额外的表达式,这些额外的表达式用于决定在每一个 DISTINCT ON分组内行的优先级。
LIMIT Clause该 LIMIT 子句由两个独立的子句组成:
LIMIT { count | ALL }
OFFSET start
count 指定最多返回多少行,而 start 指定开始返回行之前要跳过的行数。如果两者都指定,则先跳过 start 行,然后开始计数并返回 count 行。
在使用LIMIT时,用一个ORDER BY子句把 结果行约束到一个唯一顺序是个好办法。否则你将得到该查询结果行的 一个不可预测的子集 — 你可能要求从第 10 到第 20 行,但是在 什么顺序下的第 10 到第 20 呢?除非指定ORDER BY,你 是不知道顺序的。
查询规划器在生成一个查询计划时会考虑LIMIT,因此 根据你使用的LIMIT和OFFSET,你很可能 得到不同的计划(得到不同的行序)。所以,使用不同的 LIMIT/OFFSET值来选择一个查询结果的 不同子集将会给出不一致的结果,除非你 用ORDER BY强制一种可预测的结果顺序。这不是一个 缺陷,它是 SQL 不承诺以任何特定顺序(除非使用 ORDER BY来约束顺序)给出一个查询结果这一事实造 成的必然后果。
FOR UPDATE/FOR SHARE 子句FOR UPDATE 子句的形式如下:
FOR UPDATE [ OF table_name [, ...] ] [ NOWAIT ]
与它密切相关的 FOR SHARE 子句的形式如下:
FOR SHARE [ OF table_name [, ...] ] [ NOWAIT ]
FOR UPDATE使SELECT语句检索到的行像被更新一样被锁定。这防止其他事务在当前事务结束之前修改或删除它们。也就是说,其他事务对这些行尝试UPDATE、DELETE或SELECT FOR UPDATE时将被阻塞,直到当前事务结束。此外,如果来自另一个事务的UPDATE、DELETE或SELECT FOR UPDATE已经锁定了被选中的一行或多行,SELECT FOR UPDATE将等待那个事务完成,然后锁定并返回更新后的行(如果该行已被删除,则不返回行)。进一步的讨论见第 12 章。
为了防止该操作等待其他事务提交,可使用NOWAIT 选项。SELECT FOR UPDATE NOWAIT会在选中的行无法立即锁定时报错,而不是等待。注意, NOWAIT只适用于行级锁; 所需的ROW SHARE表级锁仍会按常规方式取得(见第 12 章)。 如果需要不等待就取得表级锁,可以使用 LOCK的NOWAIT选项。
FOR SHARE 的行为类似,但它在每个被检索的行上获取共享锁而非排他锁。共享锁阻塞其他事务对这些行执行 UPDATE、DELETE 或 SELECT FOR UPDATE,但不会阻止它们执行 SELECT FOR SHARE。
当前,不允许单条 SELECT 语句同时包含 FOR UPDATE 和 FOR SHARE,也不允许语句的不同部分同时使用 NOWAIT 和普通的等待模式。
如果在 FOR UPDATE 或 FOR SHARE 中提到了特定的表,则只有来自那些表的行会被锁定;SELECT 中用到的任何其他表还是被简单地照常读取。
在返回的行无法清楚地与各个表行对应起来的上下文中,不能使用 FOR UPDATE 和 FOR SHARE;例如它们不能与聚合一起使用。
避免锁定一行然后又在后面的保存点或 PL/pgSQL 异常块中修改它。后续的回滚会导致锁丢失。例如:
BEGIN; SELECT * FROM mytable WHERE key = 1 FOR UPDATE; SAVEPOINT s; UPDATE mytable SET ... WHERE key = 1; ROLLBACK TO s;
在执行 ROLLBACK 之后,该行实际上已被解锁,而不是回到保存点之前已锁定但未修改的状态。如果当前事务中锁定的行被更新或删除,或者共享锁被升级为排他锁,就会出现这种风险:在所有这些情况下,之前的锁状态都会被遗忘。如果事务随后回滚到原始锁定命令和后续更改之间的某个状态,该行将看起来完全没有被锁定。这是一个实现上的缺陷,将在 PostgreSQL 的未来版本中解决。
一条同时使用LIMIT和FOR UPDATE/SHARE子句的SELECT命令,有可能返回少于LIMIT所指定数量的行。这是因为LIMIT先被应用。该命令先选出指定数量的行,但随后可能会在试图获取其中一行或多行的锁时阻塞。一旦SELECT解除阻塞,该行可能已被删除或更新,不再满足查询的WHERE条件,这种情况下它就不会被返回。
连接表 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
...
要对所有电影的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
要对所有电影的len列求和、对结果按照 kind分组并且显示总长小于 5 小时的分组:
SELECT kind, sum(len) AS total
FROM films
GROUP BY kind
HAVING sum(len) < interval '5 hours';
kind | total
----------+-------
Comedy | 02:58
Romantic | 04:38
下面两个示例都是根据第二列(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
接下来的示例展示了如何得到表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
这个示例展示了如何在FROM子句中使用函数, 分别使用和不使用列定义列表:
CREATE FUNCTION distributors(int) RETURNS SETOF distributors AS $$
SELECT * FROM distributors WHERE did = $1;
$$ LANGUAGE SQL;
SELECT * FROM distributors(111);
did | name
-----+-------------
111 | Walt Disney
CREATE FUNCTION distributors_2(int) RETURNS SETOF record AS $$
SELECT * FROM distributors WHERE did = $1;
$$ LANGUAGE SQL;
SELECT * FROM distributors_2(111) AS (f1 int, f2 text);
f1 | f2
-----+-------------
111 | Walt Disney
当然,SELECT语句与 SQL 标准兼容。 但它也有一些扩展和缺失的特性。
FROM 子句PostgreSQL 允许省略 FROM 子句。它可以直接用于计算简单表达式的结果:
SELECT 2+2;
?column?
----------
4
其他一些 SQL 数据库必须引入一个只有一行的虚拟表,才能从该表执行 SELECT。
请注意,如果未指定 FROM 子句,查询就不能引用任何数据库表。例如,以下查询是无效的:
SELECT distributors.* WHERE distributors.name = 'Westward';
PostgreSQL 在 8.1 之前的版本会接受这种形式的查询,并为查询引用的每个表在该查询的 FROM 子句中添加一个隐式项。这种做法已不再是默认行为,因为它不符合 SQL 标准,而且被许多人认为容易出错。为了兼容依赖这一行为的应用,可以启用 add_missing_from 配置变量。
AS 关键字在 SQL 标准中,可选关键词AS只是一个噪音词,可以省略它而不影响含义。PostgreSQL解析器在重命名输出列时要求这个关键词,因为类型可扩展性特性使得没有它就会出现解析歧义。不过,AS在FROM项中是可选的。
GROUP BY和ORDER BY可用的名字空间在 SQL-92 标准中,一个ORDER BY子句只能使用输出 列名或者序号,而一个GROUP BY子句只能使用基于输 入列名的表达式。PostgreSQL扩展了 这两种子句以允许它们使用其他的选择(但如果有歧义时还是使用标准的 解释)。PostgreSQL也允许两种子句 指定任意表达式。注意出现在一个表达式中的名称将总是被当做输入列名而 不是输出列名。
SQL:1999 及其后的标准使用了一种略微不同的定义,它并不完全向后兼容 SQL-92。不过,在大部分的情况下, PostgreSQL会以与 SQL:1999 相同的 方式解释ORDER BY或GROUP BY表达式。
DISTINCT ON、LIMIT和OFFSET子句未在 SQL 标准中定义。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。