本文介绍SELECT相关的查询语句。
语法
[ WITH with_query [, ...] ]
SELECT [ ALL | DISTINCT ] select_expr [, ...]
[ FROM from_item [, ...] ]
[ WHERE condition ]
[ GROUP BY [ ALL | DISTINCT ] grouping_element [, ...] ]
[ HAVING condition]
[ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ]
[ ORDER BY expression [ ASC | DESC ] [, ...] ]
[ LIMIT [ count | ALL ] ]
参数
from_item
:有以下两种形式。table_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
from_item join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]
join_type
:表的连接类型。[ INNER ] JOIN LEFT [ OUTER ] JOIN RIGHT [ OUTER ] JOIN FULL [ OUTER ] JOIN
grouping_element
() expression
WITH从句
WITH
从句定义了一个命名好的关系以供在一个查询里面使用。 它可以扁平化嵌套查询或者简化子查询。 例如,下面的查询是等价的。
SELECT a, b
FROM (
SELECT a, MAX(b) AS b FROM t GROUP BY a
) AS x;
WITH x AS (SELECT a, MAX(b) AS b FROM t GROUP BY a)
SELECT a, b FROM x;
也同样适用于多子查询的情况。
WITH
t1 AS (SELECT a, MAX(b) AS b FROM x GROUP BY a),
t2 AS (SELECT a, AVG(d) AS d FROM y GROUP BY a)
SELECT t1.*, t2.*
FROM t1
JOIN t2 ON t1.a = t2.a;
另外,在WITH分句中定义的关系可以互相连接。
WITH
x AS (SELECT a FROM t),
y AS (SELECT a AS b FROM x),
z AS (SELECT b AS c FROM y)
SELECT c FROM z;
GROUP BY从句
GROUP BY
分句对SELECT
语句的输出进行分组,分组是匹配值的数据行。一个简单的GROUP BY
分句可以包含由输入列组成的任何表达式或者或列序号(从1开始)。
以下查询是等价的。 他们都对nationkey
列进行分组, 第一个查询使用列序号, 第二个查询使用列名。
SELECT count(*), nationkey FROM customer GROUP BY 2;
SELECT count(*), nationkey FROM customer GROUP BY nationkey;
在查询语句中没有指定列名的情况下,GROUP BY
子句也可以将输出进行分组。 例如,以下查询使用列mktsegment
进行分组,统计出customer
表的行数。
SELECT count(*) FROM customer GROUP BY mktsegment;
_col0
-------
29968
30142
30189
29949
29752
(5 rows)
在SELECT
语句中使用GROUP BY
子句时,所有输出的列要么是聚合函数,要么是GROUP BY
子句中的列。
HAVING从句
HAVING子句与聚合函数以及GROUP BY子句共同使用,用来控制选择分组。HAVING子句去掉不满足条件的分组。在分组和聚合计算完成后,HAVING对分组进行过滤。以下示例查询customer表,并进行分组,查出账户余额大于指定值的记录。
SELECT count(*), mktsegment, nationkey,
CAST(sum(acctbal) AS bigint) AS totalbal
FROM customer
GROUP BY mktsegment, nationkey
HAVING sum(acctbal) > 5700000
ORDER BY totalbal DESC;
_col0 | mktsegment | nationkey | totalbal
-------+------------+-----------+----------
1272 | AUTOMOBILE | 19 | 5856939
1253 | FURNITURE | 14 | 5794887
1248 | FURNITURE | 9 | 5784628
1243 | FURNITURE | 12 | 5757371
1231 | HOUSEHOLD | 3 | 5753216
1251 | MACHINERY | 2 | 5719140
1247 | FURNITURE | 8 | 5701952
(7 rows)
UNION|INTERSECT|EXCEPT从句
UNION、INTERSECT和EXCEPT都是全集合操作符。这些分句被用来组合多于一个查询语句的结果,最终形成一个结果。
query UNION [ALL | DISTINCT] query
query INTERSECT query
query EXCEPT query
参数ALL或DISTINCT控制最终结果集包含哪些行。如果指定参数ALL,则包含全部行,即使行完全相同。如果指定参数DISTINCT,则合并结果集,结果集只有唯一不重复的行。如果不指定参数,执行时默认使用DISTINCT。
多个集合操作符会从做到有的被处理,除非顺序通过括弧被显示指定。另外,INTERSECT比EXCEPT and UNION
有更高的优先级,意味着A UNION B INTERSECT C EXCEPT D
和这个表达式是相同的A UNION (B INTERSECT C) EXCEPT D
。
UNION
UNION把所有结果集两个结果集合并起来。下面是一个最简单的可能使用UNION分句的例子。它选择了值13并且合并了第二个选择的值42,把他们结合起来。
SELECT 13
UNION
SELECT 42;
_col0
-------
13
42
(2 rows)
INTERSECT
INTERSECT只返回那些同时在第一个和第二个查询里面都出现的行结合。下面的例子是一个最简单的可能使用INTERSECT分句的例子。它选择了值13和42并把他们和第二个查询选择的值13做合并。既然42值在第一个查询的结果集中,它并不会被包含在最终的结果集里面。
SELECT 13
INTERSECT
SELECT 13;
_col0
-------
13
(2 rows)
EXCEPT
EXCEPT返回那些行仅存在于第一个查询结果集不在第二个查询结果集中。下面是最简单的使用EXCEPT分句的例子。它选择了值42并把他们和第二个查询选择的值13做合并。既然13也同时存在于第二个查询结果集中,它不会被包含在最终的结果集中。
SELECT 42
EXCEPT
SELECT 13;
_col0
-------
42
(2 rows)
ORDER BY Clause
ORDER BY分句被用来排序一个结果集通过一个或者多个输出表达式。
ORDER BY expression [ ASC | DESC ] [, ...]
每个表达式由列名或列序号(从1开始)组成。ORDER BY
子句作为查询的最后一步,在GROUP BY
和 HAVING
子句之后。
LIMIT Clause
LIMIT分句限制了最终结果集的行数。LIMIT ALL
和略去LIMIT分句的结果一样。以下示例为查询一个大表,LIMIT子句限制它只输出5行(因为查询没有ORDER BY,所以随意返回几行)。
SELECT orderdate FROM orders LIMIT 5;
o_orderdate
-------------
1996-04-14
1992-01-15
1995-02-01
1995-11-12
1992-04-26
(5 rows)
Joins
它允许合并来自多个关联的数据。
交叉连接
SELECT *
FROM nation, region;
nation表包含了25行,region表包含了5行,所以结果两个表最终产生了125行。
子查询
一个子查询是一个包含了查询的表达式。子查询当它引用子查询之外的列时是相关的。逻辑上来说,子查询会被它的外围查询逐行评估。被引用的列将因此是固定的在子查询的评估过程中。
EXISTS
EXISTS断言决定是否一个子查询可以返回任何行。
SELECT name
FROM nation
WHERE EXISTS (SELECT * FROM region WHERE region.regionkey = nation.regionkey)
IN
IN断言决定一个子查询返回的值是否在一个被给定的结果集中。IN的结果依照对nulls的标准结果。子查询必须产生仅仅一列。
SELECT name
FROM nation
WHERE regionkey IN (SELECT regionkey FROM region)
标量子查询
标量子查询是一个非关联的子查询,返回零或者1行数据。如果这个子查询返回了多于一行的数据,那将是个错误。如果子查询没有返回任何行,则返回的结果是NULL
。
SELECT name
FROM nation
WHERE regionkey = (SELECT max(regionkey) FROM region)