跳到主要内容

SELECT 语句

SELECT 语句从数据库中检索行。

示例

从表 tbl 中选择所有列:

SELECT * FROM tbl;

tbl 中选择行:

SELECT j FROM tbl WHERE i = 3;

按列 i 分组执行聚合:

SELECT i, sum(j) FROM tbl GROUP BY i;

仅从 tbl 中选择前 3 行:

SELECT * FROM tbl ORDER BY i DESC LIMIT 3;

使用 USING 子句连接两张表:

SELECT * FROM t1 JOIN t2 USING (a, b);

使用列索引从表 tbl 中选择第 1 列和第 3 列:

SELECT #1, #3 FROM tbl;

从 addresses 表中选择所有不重复的城市:

SELECT DISTINCT city FROM addresses;

使用行变量返回一个 STRUCT

SELECT d
FROM (SELECT 1 AS a, 2 AS b) d;

语法

SELECT 语句从数据库中检索行。SELECT 语句的规范顺序如下,其中较少使用的子句采用缩进显示:

SELECT ⟨select_list⟩
FROMtables
USING SAMPLE ⟨sample_expression⟩
WHERE ⟨condition⟩
GROUP BY ⟨groups⟩
HAVING ⟨group_filter⟩
WINDOW ⟨window_expression⟩
QUALIFY ⟨qualify_filter⟩
ORDER BY ⟨order_expression⟩
LIMIT ⟨n⟩;

可选地,SELECT 语句可以以前置的 WITH clause 开始。

由于 SELECT 语句较为复杂,我们将语法图拆分为多个部分。完整语法图可在页面底部查看。

SELECT 子句

SELECT 子句 指定查询将返回的列列表。虽然它在语句中最先出现,但在逻辑上这里的表达式只会在最后执行。SELECT 子句可以包含用于转换输出的任意表达式,也可以包含聚合与窗口函数。DISTINCT 关键字可确保仅返回唯一元组。

列名不区分大小写。更多细节请参见 Rules for Case Sensitivity

FROM 子句

FROM 子句 指定查询其余部分要操作的数据来源。在逻辑上,查询从 FROM 子句开始执行。FROM 子句可以包含单张表、连接在一起的多张表组合,或者子查询节点中的另一个 SELECT 查询。

SAMPLE 子句

SAMPLE 子句 允许你基于基础表中的样本执行查询。这样可以显著加快查询处理速度,但会牺牲结果精度。在探索数据集时,样本也可用于快速查看数据快照。SAMPLE 子句会在 FROM 子句中的内容之后立即应用(即在任何连接之后、但在 where 子句或任何聚合之前)。更多信息请参见 Samples 页面。

WHERE 子句

WHERE 子句 指定应用于数据的过滤条件。这样你就可以只选择感兴趣的数据子集。在逻辑上,WHERE 子句会紧跟在 FROM 子句之后应用。

GROUP BYHAVING 子句

GROUP BY 子句 指定在 SELECT 子句中执行聚合时应使用哪些分组列。若指定了 GROUP BY 子句,则该查询始终是聚合查询,即使 SELECT 子句中没有出现聚合函数也是如此。

WINDOW 子句

WINDOW 子句 允许你指定可在窗口函数中使用的命名窗口。当存在多个窗口函数时,它可避免重复编写相同的窗口子句,因此非常有用。

QUALIFY 子句

QUALIFY 子句 用于过滤 WINDOW functions 的结果。

ORDER BYLIMITOFFSET 子句

ORDER BYLIMIT and OFFSET 是输出修饰子句。 在逻辑上,它们会在查询最后阶段应用。 ORDER BY 子句按排序条件对行进行升序或降序排序。 LIMIT 子句限制返回行数,OFFSET 子句则指示从哪个位置开始读取值。

VALUES 列表

VALUES 列表 是一组可替代 SELECT 语句提供的值。

行 ID

对于每张表,rowid pseudocolumn 会基于物理存储返回行标识符。

CREATE TABLE t (id INTEGER, content VARCHAR);
INSERT INTO t VALUES (42, 'hello'), (43, 'world');
SELECT rowid, id, content FROM t;
rowididcontent
042hello
143world

在当前存储实现中,若未删除任何行,这些标识符是连续的无符号整数(0、1、...)。 删除会在 rowid 中引入空洞,这些空洞后续可能被回收:

CREATE OR REPLACE TABLE t AS (FROM range(10) r(i));
DELETE FROM t WHERE i % 2 = 0;
SELECT rowid FROM t;
rowid
1
3
5
7
9

rowid 值在一个事务内是稳定的。

最佳实践:强烈建议避免将 rowid 用作标识符。

如果存在名为 rowid 的用户定义列,它会遮蔽 rowid 伪列。

公共表表达式

完整语法图

下面是 SELECT 语句的完整语法图: