SELECT
功能
SELECT 语句用于从单个或多个表,视图,物化视图中读取数据。SELECT 语句一般由以下子句组成:
SELECT 可以作为独立的语句也可以作为其他语句的子句,其查询结果可以作为另一个语句的输入值。
StarRocks 的查询语句基本符合 SQL-92 标准。下面介绍支持的 SELECT 用法。
说明
如果要查询 StarRocks 表、视图、或物化视图内的数据,需要有对应对象的 SELECT 权限。如果要查询 External Catalog 里的数据,需要有对应 Catalog 的 USAGE 权限。
WITH
可以在 SELECT 语句之前添加的子句,用于定义在 SELECT 内部多次引用的复杂表达式的别名。
与 CREATE VIEW 类似,但在子句中定义的表和列名在查询结束后不会持久,也不会与实际表或 VIEW 中的名称冲突。
使用 WITH 子句的好处:
-
方便和易于维护,减少查询内部的重复。
-
通过将查询中最复杂的部分抽象成单独的块,更易于阅读和理解 SQL 代码。
示例:
-- Define one subquery at the outer level, and another at the inner level as part of the
-- initial stage of the UNION ALL query.
with t1 as (select 1),t2 as (select 2)
select * from t1 union all select * from t2;
连接 (Join)
连接操作合并 2 个或多个表的数据,然后返回某些表中某些列的结果集。
目前 StarRocks 支持 Self Join、Cross Join、Inner Join、Outer Join、Semi Join 和 Anti Join。其中,Outer Join 包括 Left Join、Right Join 和 Full Join。
Join 的语法定义如下:
SELECT select_list FROM
table_or_subquery1 [INNER] JOIN table_or_subquery2 |
table_or_subquery1 {LEFT [OUTER] | RIGHT [OUTER] | FULL [OUTER]} JOIN table_or_subquery2 |
table_or_subquery1 {LEFT | RIGHT} SEMI JOIN table_or_subquery2 |
table_or_subquery1 {LEFT | RIGHT} ANTI JOIN table_or_subquery2 |
[ ON col1 = col2 [AND col3 = col4 ...] |
USING (col1 [, col2 ...]) ]
[other_join_clause ...]
[ WHERE where_clauses ]
SELECT select_list FROM
table_or_subquery1, table_or_subquery2 [, table_or_subquery3 ...]
[other_join_clause ...]
WHERE
col1 = col2 [AND col3 = col4 ...]
SELECT select_list FROM
table_or_subquery1 CROSS JOIN table_or_subquery2
[other_join_clause ...]
[ WHERE where_clauses ]
Self Join
StarRocks 支持 Self Join,即自己和自己 Join。例如同一张表的不同列进行 Join。
实际上没有特殊 的语法标识 Self Join。Self Join 中 Join 两边的条件都来自同一张表,
您需要给他们分配不同的别名。
例如:
SELECT lhs.id, rhs.parent, lhs.c1, rhs.c2 FROM tree_data lhs, tree_data rhs WHERE lhs.id = rhs.parent;
笛卡尔积 (Cross Join)
Cross join 会产生大量的结果,须慎用 cross join。
即使需要使用 Cross Join 时也需要使用过滤条件并且确保返回结果数较少。例如:
SELECT * FROM t1, t2;
SELECT * FROM t1 CROSS JOIN t2;
Inner Join
Inner Inner Join 是大家最熟知,最常用的 Join。返回的结果来自相近的两张表所请求的列,Join 的条件为两个表的列包含有相同的值。
如果两个表的某个列名相同,我们需要使用全名(table_name.column_name 形式)或者给列名起别名。
例如:
下列 3 个查询是等价的。
SELECT t1.id, c1, c2 FROM t1, t2 WHERE t1.id = t2.id;
SELECT t1.id, c1, c2 FROM t1 JOIN t2 ON t1.id = t2.id;
SELECT t1.id, c1, c2 FROM t1 INNER JOIN t2 ON t1.id = t2.id;
Outer Join
Outer Join 返回左表或者右表或者两者所有的行。如果在另一张表中没有匹配的数据,则将其设置为 NULL。例如:
SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.id = t2.id;
SELECT * FROM t1 RIGHT OUTER JOIN t2 ON t1.id = t2.id;
SELECT * FROM t1 FULL OUTER JOIN t2 ON t1.id = t2.id;
Semi Join
Left Semi Join 只返回左表中能匹配右表数据的行,不管能匹配右表多少行数据,
左表的该行最多只返回一次。Right Semi Join 原理相似,只是返回的数据是右表的。
例如:
SELECT t1.c1, t1.c2, t1.c2 FROM t1 LEFT SEMI JOIN t2 ON t1.id = t2.id;
Anti Join
Left Anti Join 只返回左表中不能匹配右表的行。
Right Anti Join 反转了这个比较,只返回右表中不能匹配左表的行。例如:
SELECT t1.c1, t1.c2, t1.c2 FROM t1 LEFT ANTI JOIN t2 ON t1.id = t2.id;
等值 Join 和非等值 Join
根据 Join 条件的不同,StarRocks 支持的上述各种类型的 Join 可以分为等值 Join 和非等值 Join,如下表所示:
| 等值 Join | Self Join、Cross Join、Inner Join、Outer Join、Semi Join 和 Anti Join |
|---|---|
| 非等值 Join | Cross Join、Inner Join,LEFT SEMI JOIN, LEFT ANTI JOIN 和 Outer Join |
-
等值 Join
等值 Join 使用等值条件作为连接条件,例如
a JOIN b ON a.id = b.id。 -
非等值 Join
非等值 Join 不使用等值条件,使用
<、<=、>、>=、<>等比较操作符,例如a JOIN b ON a.id < b.id。与等值 Join 相比,非等值 Join 目前效率较低,建议您谨慎使用。以下为非等值 Join 的两个使用示例:
SELECT t1.id, c1, c2
FROM t1
INNER JOIN t2 ON t1.id < t2.id;
SELECT t1.id, c1, c2
FROM t1
LEFT JOIN t2 ON t1.id > t2.id;
使用 USING 子句进行 Join
从 v4.0.2 版本开始,除 ON 子句外,StarRocks 还支持通过 USING 子句指定 Join 条件,便于简化具有相同列名的等值 Join。例如:SELECT * FROM t1 JOIN t2 USING (id)。
版本差异说明:
-
v4.0.2 之前的版本
USING仅作为语法糖,会在内部转换为ON条件。返回结果会包含左右两侧表的 USING 列(作为独立的列),并且支持在查询时使用表别名限定符(例如t1.id)来引用 USING 列。示例:
SELECT t1.id, t2.id FROM t1 JOIN t2 USING (id); -- 返回两个独立的 id 列 -
v4.0.2 及之后的版本
StarRocks 实现了符合 SQL 标准的
USING语义。主要功能包括:- 支持所有类型的 Join,包括
FULL OUTER JOIN。 - USING 列在结果中表示为单个合并列。对于 FULL OUTER JOIN,使用
COALESCE(left.col, right.col)语义。 - 不再支持使用表别名限定符(例如
t1.id)引用 USING 列,必须使用非限定的列名(例如id)。 - 对于
SELECT *的结果,列顺序为:[USING 列, 左表非 USING 列, 右表非 USING 列]。
示例:
SELECT t1.id FROM t1 JOIN t2 USING (id); -- ❌ 错误:列 'id' 存在歧义
SELECT id FROM t1 JOIN t2 USING (id); -- ✅ 正确:返回单个合并的 id 列
SELECT * FROM t1 FULL OUTER JOIN t2 USING (id); -- ✅ 支持 FULL OUTER JOIN - 支持所有类型的 Join,包括