From bd277f9629113d06093b767f431fb26552acf7f9 Mon Sep 17 00:00:00 2001 From: aceforeverd Date: Mon, 16 Oct 2023 20:27:11 +0800 Subject: [PATCH] docs(sql): update SQL syntax for WINDOW and JOIN SQL changes mainly from #3533 and #3554 --- .../ONLINE_REQUEST_REQUIREMENTS.md | 61 ++++++++++++++++--- docs/zh/openmldb_sql/dql/WINDOW_CLAUSE.md | 15 ++++- docs/zh/openmldb_sql/sql_difference.md | 12 ++-- 3 files changed, 69 insertions(+), 19 deletions(-) diff --git a/docs/zh/openmldb_sql/deployment_manage/ONLINE_REQUEST_REQUIREMENTS.md b/docs/zh/openmldb_sql/deployment_manage/ONLINE_REQUEST_REQUIREMENTS.md index 43b4c9e4941..1d402de8a2e 100644 --- a/docs/zh/openmldb_sql/deployment_manage/ONLINE_REQUEST_REQUIREMENTS.md +++ b/docs/zh/openmldb_sql/deployment_manage/ONLINE_REQUEST_REQUIREMENTS.md @@ -12,14 +12,23 @@ OpenMLDB仅支持上线[SELECT查询语句](../dql/SELECT_STATEMENT.md)。 下表列出了在线请求模式支持的 `SELECT` 子句。 -| SELECT 子句 | 说明 | -|:-------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------| -| 单张表的简单表达式计算 | 简单的单表查询是对一张表进行列运算、使用运算表达式或单行处理函数(Scalar Function)以及它们的组合表达式作计算。需要遵循[在线请求模式下单表查询的使用规范](#在线请求模式下单表查询的使用规范) | -| [`JOIN` 子句](../dql/JOIN_CLAUSE.md) | OpenMLDB目前仅支持**LAST JOIN**。需要遵循[在线请求模式下LAST JOIN的使用规范](#在线请求模式下-last-join-的使用规范) | +| SELECT 子句 | 说明 | +| :--------------------------------------- | :----------------------------------------------------------- | +| 无表查询 | SELECT 没有 FROM 子句, 只做表达式计算 | +| 单张表的简单表达式计算 | 简单的单表查询是对一张表进行列运算、使用运算表达式或单行处理函数(Scalar Function)以及它们的组合表达式作计算。需要遵循[在线请求模式下单表查询的使用规范](#在线请求模式下单表查询的使用规范) | +| [`JOIN` 子句](../dql/JOIN_CLAUSE.md) | OpenMLDB目前仅支持**LAST JOIN**。需要遵循[在线请求模式下LAST JOIN的使用规范](#在线请求模式下-last-join-的使用规范) | | [`WINDOW` 子句](../dql/WINDOW_CLAUSE.md) | 窗口子句用于定义一个或者若干个窗口。窗口可以是有名或者匿名的。用户可以在窗口上调用聚合函数进行分析计算。需要遵循[在线请求模式下Window的使用规范](#在线请求模式下window的使用规范) | ## 在线请求模式下 `SELECT` 子句的使用规范 +### 无表查询 + +```sql +SELECT sin(30) as out; +``` + + + ### 在线请求模式下单表查询的使用规范 - 仅支持列运算,表达式,以及单行处理函数(Scalar Function)以及它们的组合表达式运算。 @@ -57,15 +66,16 @@ SELECT substr(COL7, 3, 6) FROM t1; ### 在线请求模式下 `LAST JOIN` 的使用规范 -- 仅支持`LAST JOIN`类型。 -- 至少有一个JOIN条件是形如`left_source.column=right_source.column`的EQUAL条件,**并且`right_source.column`列需要命中右表的索引(key 列)**。 -- 带排序LAST JOIN的情况下,`ORDER BY`只支持单列的列引用表达式,列类型为 int16, int32, int64 or timestamp, **并且列需要命中右表索引的时间列**。 -- 右表 TableRef +1. 仅支持`LAST JOIN`类型。 +2. 至少有一个JOIN条件是形如`left_source.column=right_source.column`的EQUAL条件,**并且`right_source.column`列需要命中右表的索引(key 列)**。 +3. 带排序LAST JOIN的情况下,`ORDER BY`只支持单列的列引用表达式,列类型为 int16, int32, int64 or timestamp, **并且列需要命中右表索引的时间列**。满足条件 2 和 3 的情况我们简单称做表能被 LAST JOIN 的 JOIN 条件优化 +4. 右表 TableRef - 可以指一张物理表, 或者子查询语句 - 子查询情况, 只支持 - 简单列筛选 (`select * from tb` or `select id, val from tb`) - 窗口聚合子查询, 例如 `select id, count(val) over w as cnt from t1 window w as (...)`. 这种情况下, 子查询和 last join 的左表必须有相同的主表, 主表指计划树下最左边的物理表节点. - **Since OpenMLDB 0.8.0** 带 WHERE 条件过滤的简单列筛选 ( 例如 `select * from tb where id > 10`) + - **Since OpenMLDB 0.8.4** 右表是带 LAST JOIN 的子查询 `subquery`, 要求 `subquery` 最左的表能被 JOIN 条件优化, `subquery`剩余表能被自身 LAST JOIN 的 JOIN 条件优化 **Example: 支持上线的 `LAST JOIN` 语句范例** 创建两张表以供后续`LAST JOIN`。 @@ -115,15 +125,46 @@ desc t1; t1.col0 as t1_col0, t1.col1 + t2.col1 + 1 as test_col1, FROM t1 - LAST JOIN t2 ORDER BY t2.std_time ON t1.col1=t2.col1; + LAST JOIN t2 ORDER BY t2.std_time ON t1.col1=t2.col1; +``` + +右表是带 LAST JOIN 或者 WHERE 条件过滤的情况 + +```sql +CREATE TABLE t3 (col0 STRING, col1 int, std_time TIMESTAMP, INDEX(KEY=col1, TS=std_time, TTL_TYPE=absolute, TTL=30d)); +-- SUCCEED + +SELECT + t1.col1 as t1_col1, + t2.col1 as t2_col1, + t2.col0 as t2_col0 +FROM t1 LAST JOIN ( + SELECT * FROM t2 WHERE strlen(col0) > 0 +) t2 +ON t1.col1 = t2.col1 + +-- t2 被 JOIN 条件 't1.col1 = tx.t2_co1l' 优化, t3 被 JOIN 条件 't2.col1 = t3.col1' +SELECT + t1.col1 as t1_col1, + tx.t2_col1, + tx.t3_col1 +FROM t1 LAST JOIN ( + SELECT t2.col1 as t2_col1, t3.col1 as t3_col1 + FROM t2 LAST JOIN t3 + ON t2.col1 = t3.col1 +) tx +ON t1.col1 = tx.t2_col1 ``` + + ### 在线请求模式下Window的使用规范 - 窗口边界仅支持`PRECEDING`和`CURRENT ROW` - 窗口类型仅支持`ROWS`和`ROWS_RANGE`。 - 窗口`PARTITION BY`只支持列表达式,可以是多列,并且所有列需要命中索引,主表和 union source 的表都需要符合要求 -- 窗口`ORDER BY`只支持列表达式,只能是单列,并且列需要命中索引的时间列,主表和 union source 的表都需要符合要求 +- 窗口`ORDER BY`只支持列表达式,只能是单列,并且列需要命中索引的时间列,主表和 union source 的表都需要符合要求. 从 OpenMLDB 0.8.4 开始, ORDER BY 可以不写, 但需要满足额外的要求, 详见 [WINDOW CLAUSE](../dql/WINDOW_CLAUSE.md) +- **OpenMLDB 0.8.4 版本开始, 支持窗口定义不带 ORDER BY**, 具体要求如 - 可支持使用 `EXCLUDE CURRENT_ROW`,`EXCLUDE CURRENT_TIME`,`MAXSIZE`,`INSTANCE_NOT_IN_WINDOW`对窗口进行其他特殊限制,详见[OpenMLDB特有的 WindowSpec 元素](#openmldb特有的-windowspec-元素)。 - `WINDOW UNION` source 要求,支持如下格式的子查询: - 表引用或者简单列筛选,例如 `t1` 或者 `select id, val from t1`。union source 和 主表的 schema 必须完全一致,并且 union source 对应的 `PARTITION BY`, `ORDER BY` 也需要命中索引 diff --git a/docs/zh/openmldb_sql/dql/WINDOW_CLAUSE.md b/docs/zh/openmldb_sql/dql/WINDOW_CLAUSE.md index 18f49149429..c688f338527 100644 --- a/docs/zh/openmldb_sql/dql/WINDOW_CLAUSE.md +++ b/docs/zh/openmldb_sql/dql/WINDOW_CLAUSE.md @@ -119,7 +119,7 @@ partition key相等的所有行,还不是窗口,经由order by列排序后 ## 基本的 WindowSpec 语法元素 -### Window Partition Clause 和 Window OrderBy Clause +### WINDOW PARTITION BY clause 和 WINDOW ORDER BY clause ```sql WindowPartitionClause @@ -129,9 +129,18 @@ WindowOrderByClause ::= ( 'ORDER' 'BY' ByList ) ``` -`PARTITION BY`选项将查询的行分为一组进入*partitions*, 这些行在窗口函数中单独处理。`PARTITION BY`和查询级别`GROUP BY` 子句做相似的工作,除了它的表达式只能作为表达式不能作为输出列的名字或数。OpenMLDB要求必须配置`PARTITION BY`。并且目前**仅支持按列分组**,无法支持按运算和函数表达式分组。 +`PARTITION BY`选项将查询的行分为一组进入*partitions*, 这些行在窗口函数中单独处理。`PARTITION BY`和查询级别`GROUP BY` 子句做相似的工作, 只是它只能作为表达式不能作为查询结果的输出列或输出列 ID。OpenMLDB要求必须配置`PARTITION BY`。PARTITION BY list 可以有多个, 但**仅支持按列分组**,无法支持按运算或函数表达式分组。 + +`ORDER BY` 选项决定分区中的行被窗口函数处理的顺序。它和查询级别`ORDER BY`子句做相似的工作, 同样不能作为查询结果的输出列或者输出列 ID。OpenMLDB 目前**仅支持按列排序**,ORDER BY list 有且只能有一个, 不支持按运算或函数表达式排序。**OpenMLDB 0.8.4** 以后, ORDER BY 子句可以不写, 表示窗口内的列将以不确定的顺序处理, 不带 ORDER BY 子句需要满足如下条件: + +1. 不能有`EXCLUDE CURRENT_TIME` +2. 对于 ROWS 类型窗口没有更多限制, 对于 ROWS_RANGE 类型窗口: + 1. 窗口 FRAME 的边界不能是 `offset [OPEN] PRECEDING/FOLLOWING` 的格式, 目前情况只能为 `UNBOUNDED PRECEDING AND CURRENT ROW` + +```{note} +窗口不带 ORDER BY 的情况, 意味着对于在线预览模式, 计算结果是不确定的. 同时对于一些通用窗口函数, 例如 `lag, first_value`, 在所有模式下得到的计算结果都是不确定的. +``` -`ORDER BY` 选项决定分区中的行被窗口函数处理的顺序。它和查询级别`ORDER BY`子句做相似的工作, 但是同样的它不能作为输出列的名字或数。同样,OpenMLDB要求必须配置`ORDER BY`。并且目前**仅支持按列排序**,无法支持按运算和函数表达式排序。 ### Window Frame Clause diff --git a/docs/zh/openmldb_sql/sql_difference.md b/docs/zh/openmldb_sql/sql_difference.md index 3118f8f71bb..74405ee0894 100644 --- a/docs/zh/openmldb_sql/sql_difference.md +++ b/docs/zh/openmldb_sql/sql_difference.md @@ -81,7 +81,7 @@ WINDOW 子句和 GROUP BY & HAVING 子句不支持同时使用。上线时 WINDO 特殊限制: -- 在线请求模式下,WINDOW 的输入是 LAST JOIN 或者子查询内的 LAST JOIN, 注意窗口的定义里 `PARTITION BY` & `ORDER BY` 的列都必须来自 JOIN 最左边的表。 +- 在线请求模式下,WINDOW 的输入是 LAST JOIN 或者带子查询内的 LAST JOIN, 注意窗口的定义里 `PARTITION BY` & `ORDER BY` 的列都必须来自 JOIN 最左边的表。 ### GROUP BY & HAVING 子句 @@ -101,7 +101,7 @@ OpenMLDB 仅支持 LAST JOIN 一种 JOIN 语法,详细描述参考扩展语法 | **应用于** | **离线模式** | **在线预览模式** | **在线请求模式** | | ------------------------------------------------------------ | ------------ | ---------------- | ---------------- | | 两个表引用 | ✓ | ✕ | ✓ | -| 子查询, 仅包括:
左右表均为简单列筛选
左右表为 WINDOW 或 LAST JOIN 操作 | ✓ | ✓ | ✓ | +| 子查询, 仅包括:
左右表均为简单列筛选
左右表为 WINDOW 或 LAST JOIN 操作
带 WHERE 条件过滤的单表查询 | ✓ | ✓ | ✓ | 特殊限制: @@ -118,7 +118,7 @@ OpenMLDB (>= v0.7.2) 支持非递归的 WITH 子句。WITH 子句等价于其它 ### ORDER BY 关键字 -排序关键字 `ORDER BY` 仅在窗口定义 `WINDOW` 和拼表操作 `LAST JOIN` 子句内部被支持,并且不支持倒排序关键字 `DESC`。参见 WINDOW 子句和 LAST JOIN 子句内的相关说明。 +排序关键字 `ORDER BY` 仅在窗口定义 `WINDOW` 和拼表操作 `LAST JOIN` 子句内部被支持,并且不支持倒排序关键字 `DESC`。 OpenMLDB 0.8.4 以后支持窗口定义不带 ORDER BY, 但需额外满足特定条件. 参见 WINDOW 子句和 LAST JOIN 子句内的相关说明。 ### 聚合函数 @@ -149,10 +149,10 @@ OpenMLDB 主要对 `WINDOW` 以及 `LAST JOIN` 语句进行了深度定制化开 | **语句元素** | **支持语法** | **说明** | **必需 ?** | | ---------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ----------- | | 数据定义 | PARTITION BY | 可支持多列
支持的列数据类型: bool, int16, int32, int64, string, date, timestamp | ✓ | -| 数据排序 | ORDER BY | 仅支持对单一列排序
可支持数据类型: int16, int32, int64, timestamp
不支持倒序 `DESC` | ✓ | +| 数据排序 | ORDER BY | 仅支持对单一列排序
可支持数据类型: int16, int32, int64, timestamp
不支持倒序 `DESC`
OpenMLDB 0.8.4 之前必填 | - | | 范围定义 |
基本上下界定义语法:ROWS/ROWS_RANGE BETWEEN ... AND ...
支持范围定义关键字 PRECEDING, OPEN PRECEDING, CURRENT ROW, UNBOUNDED | 必须给定上下边界
不支持边界关键字 FOLLOWING
在线请求模式中,CURRENT ROW 为当前的请求行。在表格视角下,当前行将会被虚拟的插入到表格根据 ORDER BY 排序的正确位置上。 | ✓ | -| 范围单位 | ROWS
ROWS_RANGE(扩展) | ROWS_RANGE 为扩展语法,其定义的窗口边界属性等价于标准 SQL 的 RANGE 类型窗口,支持用数值或者带时间单位的数值定义窗口边界,后者为拓展语法。
带时间单位定义的窗口范围,等价于时间转化成毫秒数值后的窗口定义。例如 `ROWS_RANGE 10s PRCEDING ...` 和 `ROWS_RANGE 10000 PRECEDNG ...` 是等价的。 | ✓ | -| 窗口属性(扩展) | MAXSIZE
EXCLUDE CURRENT_ROW
EXCLUDE CURRENT_TIME
INSTANCE_NOT_IN_WINDOW | MAXSIZE 只对 ROWS_RANGE 有效 | - | +| 范围单位 | ROWS
ROWS_RANGE(扩展) | ROWS_RANGE 为扩展语法,其定义的窗口边界属性等价于标准 SQL 的 RANGE 类型窗口,支持用数值或者带时间单位的数值定义窗口边界,后者为拓展语法。
带时间单位定义的窗口范围,等价于时间转化成毫秒数值后的窗口定义。例如 `ROWS_RANGE 10s PRCEDING ...` 和 `ROWS_RANGE 10000 PRECEDNG ...` 是等价的。 | ✓ | +| 窗口属性(扩展) | MAXSIZE
EXCLUDE CURRENT_ROW
EXCLUDE CURRENT_TIME
INSTANCE_NOT_IN_WINDOW | MAXSIZE 只对 ROWS_RANGE 有效
不带 ORDER BY 和 EXCLUDE CURRENT_TIME 不能同时使用 | - | | 多表定义(扩展) | 实际使用中语法形态较为复杂,参考:
[跨表特征开发教程](../tutorial/tutorial_sql_2.md)
[WINDOW UNION 语法文档](../openmldb_sql/dql/WINDOW_CLAUSE.md#1-window--union) | 允许合并多个表
允许联合简单子查询
实践中,一般和聚合函数搭配使用,实现跨表的聚合操作 | - | | 匿名窗口 | - | 必须包括 PARTITION BY、ORDER BY、以及窗口范围定义 | - |