Table expression 包含几个子句:FROM
,WHERE
,GROUP BY
和 HAVING
。DB 在处理查询语句的顺序是:
- 从
FROM
指示的表中拿出数据 - 如果有
JOIN
,按JOIN
的条件组合数据 - 按
WHERE
筛选数据 - 按
GROUP BY
聚合数据 - 按
HAVING
筛选聚合后的数据
The FROM
Clause
语法:
FROM table_reference [, table_reference [, ...]]
Table reference 可以是:
- 一个表名
- 派生的表,比如子查询所产生的表
- JOIN 结构
- 上述几项的组合
多个 table reference 一起出现在 FROM
子句中时,它们是 cross-joined(交叉相联)的。Join 后的结果作为一个虚拟表继续被处理。
Joined Tables 重要
See SQL: Queries: Table Expressions: Join.
Table And Column Aliases 重要
See SQL: Queries: Table Expressions: Alias.
Subqueries 重要
子查询在 SQL 语句中被括号包起,并且需要指定一个表别名。它的查询结果作为一张虚拟表继续被处理。例如:
FROM (SELECT * FROM table1) AS <alias_name>
子查询也可以是一个 VALUES
列表:
FROM (VALUES ('anne', 'smith'), ('bob', 'jones'), ('joe', 'blow'))
AS names(first, last)
Table Functions 不重要
少看到有人使用,略。
LATERAL
Subqueries 不重要
少看到有人使用,略。
The WHERE
Clause 重要
WHERE
相对简单,它接受一个返回 boolean 值的表达式。常见示例:
SELECT ... FROM fdt WHERE c1 > 5
SELECT ... FROM fdt WHERE c1 IN (1, 2, 3)
SELECT ... FROM fdt WHERE c1 IN (SELECT c1 FROM t2)
SELECT ... FROM fdt WHERE c1 IN (SELECT c3 FROM t2 WHERE c2 = fdt.c1 + 10)
SELECT ... FROM fdt WHERE c1 BETWEEN (SELECT c3 FROM t2 WHERE c2 = fdt.c1 + 10) AND 100
SELECT ... FROM fdt WHERE EXISTS (SELECT c1 FROM t2 WHERE c2 > fdt.c1)
The GROUP BY
and HAVING
Clauses 重要
GROUP BY
会把某列里面同样的值聚合成一行返回:
=> SELECT * FROM test1;
x | y
---+---
a | 3
c | 2
b | 5
a | 1
(4 rows)
=> SELECT x FROM test1 GROUP BY x;
x
---
a
b
c
(3 rows)
它经常跟聚合函数(aggregate function)一起配合使用,比如 sum()
:
=> SELECT x, sum(y) FROM test1 GROUP BY x;
x | sum
---+-----
a | 4
b | 5
c | 2
(3 rows)
=> SELECT product_id, p.name, (sum(s.units) * p.price) AS sales
FROM products p LEFT JOIN sales s USING (product_id)
GROUP BY product_id, p.name, p.price;
在 PG 中,GROUP BY
后面的列可以是 SELECT
中的列,也可以是某个 value expression(没有示例)。
HAVING
子句则是在 GROUP BY
之后做一轮筛选:
SELECT product_id, p.name, (sum(s.units) * (p.price - p.cost)) AS profit
FROM products p LEFT JOIN sales s USING (product_id)
WHERE s.date > CURRENT_DATE - INTERVAL '4 weeks'
GROUP BY product_id, p.name, p.price, p.cost
HAVING sum(p.price * s.units) > 5000;
HAVING
中的条件,可以使用聚合函数也可以不使用(WHERE
中的条件则无法使用聚合函数);这些条件也不必跟 SELECT
列表中的某项一致,比如上面例子中的 sum(p.price * s.units)
并没有出现在 SELECT
列表中。
GROUPING SETS
, CUBE
, and ROLLUP
不重要
略。
Window Function Processing 不重要
略。