Skip to content

Commit 1c153e0

Browse files
authored
docs(sql): update SQL syntax for WINDOW and JOIN (#3555)
New SQLs: - WINDOW without order by - LEFT JOIN - LAST JOIN ( LAST JOIN ) - LAST JOIN ( WINDOW )
1 parent 4433970 commit 1c153e0

File tree

4 files changed

+142
-41
lines changed

4 files changed

+142
-41
lines changed

docs/zh/openmldb_sql/deployment_manage/ONLINE_REQUEST_REQUIREMENTS.md

+84-13
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ OpenMLDB仅支持上线[SELECT查询语句](../dql/SELECT_STATEMENT.md)。
1212

1313
下表列出了在线请求模式支持的 `SELECT` 子句。
1414

15-
| SELECT 子句 | 说明 |
16-
|:-------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------|
17-
| 单张表的简单表达式计算 | 简单的单表查询是对一张表进行列运算、使用运算表达式或单行处理函数(Scalar Function)以及它们的组合表达式作计算。需要遵循[在线请求模式下单表查询的使用规范](#在线请求模式下单表查询的使用规范) |
18-
| [`JOIN` 子句](../dql/JOIN_CLAUSE.md) | OpenMLDB目前仅支持**LAST JOIN**。需要遵循[在线请求模式下LAST JOIN的使用规范](#在线请求模式下-last-join-的使用规范) |
15+
| SELECT 子句 | 说明 |
16+
| :--------------------------------------- | :----------------------------------------------------------- |
17+
| 单张表的简单表达式计算 | 简单的单表查询是对一张表进行列运算、使用运算表达式或单行处理函数(Scalar Function)以及它们的组合表达式作计算。需要遵循[在线请求模式下单表查询的使用规范](#在线请求模式下单表查询的使用规范) |
18+
| [`JOIN` 子句](../dql/JOIN_CLAUSE.md) | OpenMLDB目前仅支持**LAST JOIN**。需要遵循[在线请求模式下LAST JOIN的使用规范](#在线请求模式下-last-join-的使用规范) |
1919
| [`WINDOW` 子句](../dql/WINDOW_CLAUSE.md) | 窗口子句用于定义一个或者若干个窗口。窗口可以是有名或者匿名的。用户可以在窗口上调用聚合函数进行分析计算。需要遵循[在线请求模式下Window的使用规范](#在线请求模式下window的使用规范) |
2020

2121
## 在线请求模式下 `SELECT` 子句的使用规范
@@ -57,15 +57,19 @@ SELECT substr(COL7, 3, 6) FROM t1;
5757

5858
### 在线请求模式下 `LAST JOIN` 的使用规范
5959

60-
- 仅支持`LAST JOIN`类型。
61-
- 至少有一个JOIN条件是形如`left_source.column=right_source.column`的EQUAL条件,**并且`right_source.column`列需要命中右表的索引(key 列)**
62-
- 带排序LAST JOIN的情况下,`ORDER BY`只支持单列的列引用表达式,列类型为 int16, int32, int64 or timestamp, **并且列需要命中右表索引的时间列**
63-
- 右表 TableRef
60+
1. 仅支持`LAST JOIN`类型。
61+
2. 至少有一个JOIN条件是形如`left_source.column=right_source.column`的EQUAL条件,**并且`right_source.column`列需要命中右表的索引(key 列)**
62+
3. 带排序LAST JOIN的情况下,`ORDER BY`只支持单列的列引用表达式,列类型为 int64 timestamp, **并且列需要命中右表索引的时间列**满足条件 2 和 3 的情况我们简单称做表能被 LAST JOIN 的 JOIN 条件优化
63+
4. 右表 TableRef
6464
- 可以指一张物理表, 或者子查询语句
65-
- 子查询情况, 只支持
65+
- 子查询情况, 目前支持
6666
- 简单列筛选 (`select * from tb` or `select id, val from tb`)
67-
- 窗口聚合子查询, 例如 `select id, count(val) over w as cnt from t1 window w as (...)`. 这种情况下, 子查询和 last join 的左表必须有相同的主表, 主表指计划树下最左边的物理表节点.
68-
- **Since OpenMLDB 0.8.0** 带 WHERE 条件过滤的简单列筛选 ( 例如 `select * from tb where id > 10`)
67+
- 窗口聚合子查询, 例如 `select id, count(val) over w as cnt from t1 window w as (...)`.
68+
- OpenMLDB 0.8.4 之前, 如果 LAST JOIN 的右表是窗口聚合子查询, 需要和 LAST JOIN 的左表输入有相同的主表
69+
- [ALPHA] OpenMLDB >= 0.8.4, 允许 LAST JOIN 下的窗口聚合子查询不带主表. 详细见下面的例子
70+
- **OpenMLDB >= 0.8.0** 带 WHERE 条件过滤的简单列筛选 ( 例如 `select * from tb where id > 10`)
71+
- **[ALPHA] OpenMLDB >= 0.8.4** 右表是带 LAST JOIN 的子查询 `subquery`, 要求 `subquery` 最左的表能被 JOIN 条件优化, `subquery`剩余表能被自身 LAST JOIN 的 JOIN 条件优化
72+
- **[ALPHA] OpenMLDB >= 0.8.4** LEFT JOIN. 要求 LEFT JOIN 的右表能被 LEFT JOIN 条件优化, LEFT JOIN 的左表能被上层的 LAST JOIN 条件优化
6973

7074
**Example: 支持上线的 `LAST JOIN` 语句范例**
7175
创建两张表以供后续`LAST JOIN`
@@ -115,15 +119,82 @@ desc t1;
115119
t1.col0 as t1_col0,
116120
t1.col1 + t2.col1 + 1 as test_col1,
117121
FROM t1
118-
LAST JOIN t2 ORDER BY t2.std_time ON t1.col1=t2.col1;
122+
LAST JOIN t2 ORDER BY t2.std_time ON t1.col1=t2.col1;
119123
```
120124

125+
右表是带 LAST JOIN 或者 WHERE 条件过滤的情况
126+
127+
```sql
128+
CREATE TABLE t3 (col0 STRING, col1 int, std_time TIMESTAMP, INDEX(KEY=col1, TS=std_time, TTL_TYPE=absolute, TTL=30d));
129+
-- SUCCEED
130+
131+
SELECT
132+
t1.col1 as t1_col1,
133+
t2.col1 as t2_col1,
134+
t2.col0 as t2_col0
135+
FROM t1 LAST JOIN (
136+
SELECT * FROM t2 WHERE strlen(col0) > 0
137+
) t2
138+
ON t1.col1 = t2.col1
139+
140+
-- t2 被 JOIN 条件 't1.col1 = tx.t2_co1l' 优化, t3 被 JOIN 条件 't2.col1 = t3.col1'
141+
SELECT
142+
t1.col1 as t1_col1,
143+
tx.t2_col1,
144+
tx.t3_col1
145+
FROM t1 LAST JOIN (
146+
SELECT t2.col1 as t2_col1, t3.col1 as t3_col1
147+
FROM t2 LAST JOIN t3
148+
ON t2.col1 = t3.col1
149+
) tx
150+
ON t1.col1 = tx.t2_col1
151+
152+
-- 右表是 LEFT JOIN
153+
SELECT
154+
t1.col1 as t1_col1,
155+
tx.t2_col1,
156+
tx.t3_col1
157+
FROM t1 LAST JOIN (
158+
SELECT t2.col1 as t2_col1, t3.col1 as t3_col1
159+
FROM t2 LEFT JOIN t3
160+
ON t2.col1 = t3.col1
161+
) tx
162+
ON t1.col1 = tx.t2_col1
163+
164+
-- OpenMLDB 0.8.4 之前, LAST JOIN 窗口子查询需要窗口的子查询主表和当前主表一致
165+
-- 这里都是 t1
166+
SELECT
167+
t1.col1,
168+
tx.agg
169+
FROM t1 LAST JOIN (
170+
SELECT col1, count(col2) over w as agg
171+
FROM t1 WINDOW w AS (
172+
UNION t2
173+
PARTITION BY col2 order by std_time ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
174+
INSTANCE_NOT_IN_WINDOW EXCLUDE CURRENT_ROW
175+
)
176+
)
177+
178+
-- 右表是窗口聚合计算
179+
-- OpenMLDB >= 0.8.4, 允许 t1 LAST JOIN WINDOW (t2). t1 是主表, t2 是一张副表
180+
-- 此 SQL 和上一个例子语义一致
181+
SELECT
182+
t1.col1,
183+
tx.agg
184+
FROM t1 LAST JOIN (
185+
SELECT col1, count(col2) over w as agg
186+
FROM t2 WINDOW w AS (PARTITION BY col2 order by std_time ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
187+
)
188+
```
189+
190+
191+
121192
### 在线请求模式下Window的使用规范
122193

123194
- 窗口边界仅支持`PRECEDING``CURRENT ROW`
124195
- 窗口类型仅支持`ROWS``ROWS_RANGE`
125196
- 窗口`PARTITION BY`只支持列表达式,可以是多列,并且所有列需要命中索引,主表和 union source 的表都需要符合要求
126-
- 窗口`ORDER BY`只支持列表达式,只能是单列,并且列需要命中索引的时间列,主表和 union source 的表都需要符合要求
197+
- 窗口`ORDER BY`只支持列表达式,只能是单列,并且列需要命中索引的时间列,主表和 union source 的表都需要符合要求. 从 OpenMLDB 0.8.4 开始, ORDER BY 可以不写, 但需要满足额外的要求, 详见 [WINDOW CLAUSE](../dql/WINDOW_CLAUSE.md)
127198
- 可支持使用 `EXCLUDE CURRENT_ROW``EXCLUDE CURRENT_TIME``MAXSIZE``INSTANCE_NOT_IN_WINDOW`对窗口进行其他特殊限制,详见[OpenMLDB特有的 WindowSpec 元素](#openmldb特有的-windowspec-元素)
128199
- `WINDOW UNION` source 要求,支持如下格式的子查询:
129200
- 表引用或者简单列筛选,例如 `t1` 或者 `select id, val from t1`。union source 和 主表的 schema 必须完全一致,并且 union source 对应的 `PARTITION BY`, `ORDER BY` 也需要命中索引

docs/zh/openmldb_sql/dql/JOIN_CLAUSE.md

+20-9
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
11
# JOIN Clause
22

3-
OpenMLDB目前仅支持`LAST JOIN`一种**JoinType**
3+
OpenMLDB目前支持
44

5-
LAST JOIN可以看作一种特殊的LEFT JOIN。在满足JOIN条件的前提下,左表的每一行拼接符合条件的最后一行。LAST JOIN分为无排序拼接,和排序拼接。
5+
- LAST JOIN
6+
- LEFT JOIN (**OPENMLDB >= 0.8.4**)
7+
8+
LEFT OUTER JOIN (或者简称 LEFT JOIN) 会将两个 from_item 进行联接, 同时保留左侧from_item中的所有记录, 即使右侧from_item满足联接条件的记录数为零。对于右侧表中没有找到匹配的记录,则右侧的列会以 NULL 值填充。
9+
10+
LAST JOIN 是 OpenMLDB SQL 拓展的 JOIN类型. 它的语法和 LEFT JOIN 基本一致, 但在右侧 from_item 后面允许带可选的 ORDER BY 子句, 表示筛选右侧 from_iem 的顺序. 根据是否带有这个 ORDER BY 子句, LAST JOIN分为无排序拼接,和排序拼接。
611

712
- 无排序拼接是指:未对右表作排序,直接拼接。
813
- 排序拼接是指:先对右表排序,然后再拼接。
914

10-
与LEFT JOIN相同,LAST JOIN也会返回左表中所有行,即使右表中没有匹配的行。
15+
与LEFT JOIN相同,LAST JOIN也会返回左表中所有行,即使右表中没有匹配的行。不同的是, LAST JOIN 是一对一, LEFT JOIN 是一对多.
1116

1217
## Syntax
1318

1419
```
15-
JoinClause
16-
::= TableRef JoinType 'JOIN' TableRef [OrderByClause] 'ON' Expression
20+
join:
21+
TableRef "LAST" "JOIN" TableRef [OrderByClause] "ON" Expression
22+
| TableRef join_type "JOIN" TableRef "ON" Expression
1723
18-
JoinType ::= 'LAST'
24+
join_type:
25+
'LEFT' [OUTER]
1926
20-
OrderByClause := 'ORDER' 'BY' <COLUMN_NAME>
27+
order_by_clause:
28+
'ORDER' 'BY' <COLUMN_NAME>
2129
```
2230

2331
### 使用限制说明
@@ -30,14 +38,17 @@ OrderByClause := 'ORDER' 'BY' <COLUMN_NAME>
3038
## SQL语句模版
3139

3240
```sql
33-
SELECT ... FROM table_ref LAST JOIN table_ref ON expression;
41+
SELECT ... FROM t1 LAST JOIN t2 ON expression;
42+
43+
SELECT ... FROM t1 LEFT JOIN t2 ON expression;
3444
```
3545

3646
## 边界说明
3747

3848
| SELECT语句元素 | 离线模式 | 在线预览模式 | 在线请求模式 | 说明 |
3949
| :--------------------------------------------- | --------- | ------------ | ------------ |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
40-
| JOIN Clause| **````** | **``x``** | **````** | 表示数据来源多个表JOIN。OpenMLDB目前仅支持LAST JOIN。在线请求模式下,需要遵循[在线请求模式下LAST JOIN的使用规范](../deployment_manage/ONLINE_REQUEST_REQUIREMENTS.md#在线请求模式下-last-join-的使用规范) |
50+
| LAST JOIN | **````** | **``x``** | **````** | 表示数据来源多个表JOIN。在线请求模式下,需要遵循[在线请求模式下LAST JOIN的使用规范](../deployment_manage/ONLINE_REQUEST_REQUIREMENTS.md#在线请求模式下-last-join-的使用规范) |
51+
| LEFT JOIN | **``x``** | **``x``** | **````** | 由于 LEFT JOIN 是一对多 JOIN, 本身不能直接用于在线请求模式. 但是可以作为其他类型查询内部的子查询, 例如作为 LAST JOIN 的右表. 具体参考[在线请求模式下LAST JOIN的使用规范](../deployment_manage/ONLINE_REQUEST_REQUIREMENTS.md#在线请求模式下-last-join-的使用规范) |
4152

4253

4354
### 未排序的LAST JOIN

docs/zh/openmldb_sql/dql/WINDOW_CLAUSE.md

+12-3
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ SELECT select_expr [,select_expr...], window_function_name(expr) OVER window_nam
135135

136136
## 基本的 WindowSpec 语法元素
137137

138-
### Window Partition Clause 和 Window OrderBy Clause
138+
### WINDOW PARTITION BY clause 和 WINDOW ORDER BY clause
139139

140140
```sql
141141
WindowPartitionClause
@@ -145,9 +145,18 @@ WindowOrderByClause
145145
::= ( 'ORDER' 'BY' ByList )
146146
```
147147

148-
`PARTITION BY`选项将查询的行分为一组进入*partitions*, 这些行在窗口函数中单独处理。`PARTITION BY`和查询级别`GROUP BY` 子句做相似的工作,除了它的表达式只能作为表达式不能作为输出列的名字或数。OpenMLDB要求必须配置`PARTITION BY`。并且目前**仅支持按列分组**,无法支持按运算和函数表达式分组。
148+
`PARTITION BY`选项将查询的行分为一组进入*partitions*, 这些行在窗口函数中单独处理。`PARTITION BY`和查询级别`GROUP BY` 子句做相似的工作, 只是它只能作为表达式不能作为查询结果的输出列或输出列 ID。OpenMLDB要求必须配置`PARTITION BY`。PARTITION BY list 可以有多个, 但**仅支持按列分组**,无法支持按运算或函数表达式分组。
149+
150+
`ORDER BY` 选项决定分区中的行被窗口函数处理的顺序。它和查询级别`ORDER BY`子句做相似的工作, 同样不能作为查询结果的输出列或者输出列 ID。OpenMLDB 目前**仅支持按列排序**,ORDER BY list 有且只能有一个, 不支持按运算或函数表达式排序。**OpenMLDB 0.8.4** 以后, 在线模式下 ORDER BY 子句可以不写 (离线模式暂时不支持), 表示窗口内的列将以不确定的顺序处理, 不带 ORDER BY 子句的窗口需要额外满足如下条件:
151+
152+
1. 不能有`EXCLUDE CURRENT_TIME`
153+
2. 对于 ROWS 类型窗口没有更多限制, 对于 ROWS_RANGE 类型窗口:
154+
1. 窗口 FRAME 的边界不能是 `offset [OPEN] PRECEDING/FOLLOWING` 的格式, 目前情况只能为 `UNBOUNDED PRECEDING AND CURRENT ROW`
155+
156+
```{note}
157+
窗口不带 ORDER BY 的情况, 意味着对于在线预览模式, 计算结果是不确定的, 无法预测哪些行进去了窗口哪些行没有. 同时对于一些通用窗口函数, 例如 `lag, first_value`, 在所有模式下得到的计算结果都是不确定的,无法预测窗口内行的先后顺序.
158+
```
149159

150-
`ORDER BY` 选项决定分区中的行被窗口函数处理的顺序。它和查询级别`ORDER BY`子句做相似的工作, 但是同样的它不能作为输出列的名字或数。同样,OpenMLDB要求必须配置`ORDER BY`。并且目前**仅支持按列排序**,无法支持按运算和函数表达式排序。
151160

152161
### Window Frame Clause
153162

0 commit comments

Comments
 (0)