TDengine 新功能 JOIN

1. 背景

目前 TDengine 只实现了 Inner Join 功能,本次 Join 功能增强将支持除 Cross Join 等时序数据库中基本没有需求场景的 Join 类型外的所有 Join 类型,包括传统库中的 Left Join、Right Join、Full Join、Semi Join、Anti-Semi Join 以及时序库中特色的 ASOF Join、Window Join。

所有拟支持的 Join 组合如下表所示:

None

Semi

Anti-Semi

ASOF

Window

Inner

支持

/

/

/

/

Left

支持

支持

支持

支持

支持

Right

支持

支持

支持

支持

支持

Full

支持

/

/

/

/

注:上表中之所以存在一些不支持的 Join 组合,主要原因是这些 Join 类型(Semi、Anti-Semi、ASOF、Window)是有明确的单向性的,其查询结果也跟这种单向性紧密相关,因此 Inner Join 或 Full Join 与他们的组合将产生矛盾性。以 Semi Join 为例,通常表达的是操作符 IN 的语义,查询结果也通常只有源表的数据,当同时存在反向查询时,这种查询结果将失去意义。因此对于这些组合来说 TDengine 不提供显式支持,如果需要可以通过 SQL 语句的组合来实现,例如通过 UNION 语句获得更精确的双向语义。

除了上述 Join 支持范围大幅增强外,另一个需求是支持主键列的 timetruncate 函数,具体来说就是支持主键列进行 timetruncate 后进行关联查询。通过这个功能增强,可以将一系列的相关时间戳转换为同一个时间戳,进而在关联查询时可以实现按时间区间 Join 的目的。

本次涉及的所有功能开发和增强在开源版中实现。

2. 定义

  • 驱动表:驱动关联查询进行的表,在 Left Join 系列中左表为驱动表,在 Right Join 系列中右表为驱动表。

  • 主键列:本文中提到的主键列都指的是 TDengine 中第一列,即主键时间戳列,与复合主键新增的主键列无关。

  • 等值条件:通过等号(=)运算符指定的运算条件;

  • 连接条件:连接条件是指进行表关联所指定的条件,TDengine 支持的所有关联查询都需要指定连接条件,连接条件通常(Inner Join 和 Window Join 例外)只出现在 ON 之后。根据语义,Inner Join 中出现在 WHERE 之后的条件也可以视作连接条件,而 Window Join 是通过 WINDOW_OFFSET 来指定连接条件。

  • 过滤条件:过滤条件是指对表关联的结果进行过滤的条件,通过 WHERE 子句进行指定。

  • 主连接条件:作为一款时序数据库,TDengine 所有的关联查询都围绕主键时戳列进行,因此要求除 ASOF/Window Join 外的所有关联查询都必须含有主键列的等值连接条件,而按照顺序首次出现在连接条件中的主键列等值连接条件将会被作为主连接条件。ASOF Join 的主连接条件可以包含非等值的连接条件,而 Window Join 的主连接条件则是通过 WINDOW_OFFSET 来指定。

  • 分组条件:时序数据库特色的 ASOF/Window Join (其他 Join 不支持)支持对关联查询的输入数据进行分组,然后每个分组内进行关联操作。分组只对关联查询的输入进行,输出结果将不包含分组信息。ASOF/Window Join 中出现在 ON 之后的等值条件(ASOF 的主连接条件除外)将被作为分组条件。

3 内容

3.1 连接条件

除 ASOF Join 外,TDengine 支持的所有 Join 类型都必须显式指定连接条件,ASOF Join 因为默认定义有隐式的连接条件,所以(在默认条件可以满足需求的情况下)可以不必显式指定连接条件。

除 ASOF/Window Join 外,连接条件中除了包含主连接条件外,还可以包含任意多条其他连接条件,主连接条件与其他连接条件间必须是 AND 关系,而其他连接条件之间则没有这个限制。其他连接条件中可以包含主键列、TAG 、普通列、常量及其标量函数或运算的任意逻辑运算组合。

以智能电表为例,下面这几条 SQL 都包含合法的连接条件:

SELECT a.* FROM meters a LEFT JOIN meters b ON a.ts = b.ts AND a.ts > '2023-10-18 10:00:00.000'; SELECT a.* FROM meters a LEFT JOIN meters b ON a.ts = b.ts AND (a.ts > '2023-10-18 10:00:00.000' OR a.ts < '2023-10-17 10:00:00.000'); SELECT a.* FROM meters a LEFT JOIN meters b ON timetruncate(a.ts, 1s) = timetruncate(b.ts, 1s) AND (a.ts + 1s > '2023-10-18 10:00:00.000' OR a.groupId > 0); SELECT a.* FROM meters a LEFT ASOF JOIN meters b ON timetruncate(a.ts, 1s) < timetruncate(b.ts, 1s) AND a.groupId = b.groupId;

3.2 主键时间线

TDengine 作为时序数据库要求每个表(子表)中必须有主键时间戳列,它将作为该表的主键时间线进行很多跟时间相关的运算,而子查询的结果或者 Join 运算的结果中也需要明确哪一列将被视作主键时间线参与后续的时间相关的运算。在子查询中,查询结果中存在的有序的第一个出现的主键列(或其运算)或等同主键列的伪列(_wstart/_wend)将被视作该输出表的主键时间线;Join 输出结果中主键时间线的选择遵从以下规则:

  • Left/Right Join 系列中驱动表(子查询)的主键列将被作为后续查询的主键时间线;此外,在 Window Join 窗口内,因为左右表同时有序所以在窗口内可以把任意一个表的主键列做作主键时间线,优先选择本表的主键列作为主键时间线;

  • Inner Join 可以把任意一个表的主键列做作主键时间线,当存在类似分组条件(TAG 列的等值条件且与主连接条件 AND 关系)时将无法产生主键时间线;

  • Full Join 因为无法产生任何一个有效的主键时间序列,因此没有主键时间线,这也就意味着 Full Join 中无法进行时间线相关的运算。

示例

以下文 4.3 节所示示例数据为例,部分 SQL 及运行结果如下:

SQL 语句

查询结果

说明

SELECT diff(a.col1) FROM sta a

                            JOIN sta b ON a.ts = b.ts AND a.tg1 = b.tg1

错误

因为缺少主键时间线报错

3.3 示例数据

这里假设存在超级表 sta 含有两张子表 tba1 和 tba2,各自的行列数据如下:

tba1

tba2

ts

col1

tg1(tag)

ts

col1

tg1(tag)

2023-11-17 16:29:00

1

1

2023-11-17 16:29:00

2

2

2023-11-17 16:29:02

3

1

2023-11-17 16:29:01

3

2

2023-11-17 16:29:03

4

1

2023-11-17 16:29:03

5

2

2023-11-17 16:29:04

5

1

2023-11-17 16:29:05

7

2

后续所有 Join 查询示例以此节示例数据作为输入数据。

3.4 Join 功能

3.4.1 Inner Join

含义

内连接 - 只有左右表中同时符合连接条件的数据才会被返回,可以视为两个表符合连接条件的数据的交集。

语法

SELECT ... FROM table_name1 [INNER] JOIN table_name2 [ON ...] [WHERE ...] [...] 或 SELECT ... FROM table_name1, table_name2 WHERE ... [...]

结果集

符合连接条件的左右表行数据的笛卡尔积集合。

适用范围

支持超级表、普通表、子表、子查询间 Inner Join。

说明
  • 对于第一种语法,INNER 关键字可选, ON 和/或 WHERE 中可以指定主连接条件和其他连接条件,WHERE 中还可以指定过滤条件,ON/WHERE 两者至少指定一个;

  • 对于第二种语法,可以在 WHERE 中指定主连接条件、其他连接条件、过滤条件;

  • 对超级表进行 Inner Join 时,与主连接条件 AND 关系的 Tag 列等值条件将作为类似分组条件使用,因此输出结果不能保持有序。

示例

SQL 语句

查询结果

SELECT a.col1, b.col1 FROM tba1 a JOIN tba2 b ON a.ts = b.ts

1

4

2

5

SELECT a.col1, b.col1 FROM sta a JOIN sta b ON a.ts = b.ts AND a.ts < '2023-11-17 16:29:02'

1

1

2

2

3

1

2

1

2

3

3.4.2 Left Outer Join

含义

左(外)连接 - 既包含左右表同时符合连接条件的数据集合,也包括左表中不符合连接条件的数据集合。

语法

SELECT ... FROM table_name1 LEFT [OUTER] JOIN table_name2 ON ... [WHERE ...] [...]

结果集

Inner Join 的结果集 + 左表中不符合连接条件的行和右表的空数据(NULL)组成的行数据集合。

适用范围

支持超级表、普通表、子表、子查询间 Left Join。

说明
  • OUTER 关键字可选;

示例

SQL 语句

查询结果

SELECT a.col1, b.col1 FROM sta a LEFT JOIN sta b ON a.ts = b.ts AND a.ts < '2023-11-17 16:29:02' AND b.ts < '2023-11-17 16:29:01'

1

1

2

2

3

3

4

5

5

7

1

2

1

2

NULL

NULL

NULL

NULL

NULL

NULL

SELECT a.col1, b.col1 FROM sta a LEFT JOIN sta b ON a.ts = b.ts WHERE a.ts < '2023-11-17 16:29:02' AND b.ts < '2023-11-17 16:29:01' ORDER BY a.col1, b.col1;

1

1

2

2

1

2

1

2

3.4.3 Left Semi Join

含义

左半连接 - 通常表达的是 IN/EXISTS 的含义,即对左表任意一条数据来说,只有当右表中存在任一符合连接条件的数据时才返回左表行数据。

语法

SELECT ... FROM table_name1 LEFT SEMI JOIN table_name2 ON ... [WHERE ...] [...]

结果集

左表中符合连接条件的行和右表任一符合连接条件的行组成的行数据集合。

适用范围

支持超级表、普通表、子表、子查询间 Left Semi Join。

示例

SQL 语句

查询结果

SELECT a.ts, b.ts FROM sta a LEFT SEMI JOIN sta b ON a.ts = b.ts AND a.ts < '2023-11-17 16:29:02'

2023-11-17 16:29:00

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:00

2023-11-17 16:29:00

2023-11-17 16:29:01

3.4.4 Left Anti-Semi Join

含义

左反连接 - 同左半连接的逻辑正好相反,通常表达的是 NOT IN/NOT EXISTS 的含义,即对左表任意一条数据来说,只有当右表中不存在任何符合连接条件的数据时才返回左表行数据。

语法

SELECT ... FROM table_name1 LEFT ANTI JOIN table_name2 ON ... [WHERE ...] [...]

结果集

左表中不符合连接条件的行和右表的空数据(NULL)组成的行数据集合。

适用范围

支持超级表、普通表、子表、子查询间 Left Anti-Semi Join。

示例

SQL 语句

查询结果

SELECT a.ts, b.ts FROM tba1 a LEFT ANTI JOIN tba2 b ON a.ts = b.ts

2023-11-17 16:29:02

2023-11-17 16:29:04

NULL

NULL

3.4.5 Left ASOF Join

含义

左不完全匹配连接 - 不同于其他传统 Join 的完全匹配模式,ASOF Join 允许以指定的匹配模式进行不完全匹配,即按照主键时间戳最接近的方式进行匹配。

语法

SELECT ... FROM table_name1 LEFT ASOF JOIN table_name2 [ON ...] [JLIMIT jlimit_num] [WHERE ...] [...]

结果集

左表中每一行数据与右表中符合连接条件的按主键列排序后时间戳最接近的最多 jlimit_num 条数据或空数据(NULL)的笛卡尔积集合。

适用范围

支持超级表、普通表、子表间 Left ASOF Join。

说明
  • 只支持表间 ASOF Join,不支持子查询间 ASOF Join;

  • ON 子句中支持指定主键列或主键列的 timetruncate 函数运算(不支持其他标量运算及函数)后的单个匹配规则(主连接条件),支持的运算符及其含义如下:

    运算符

    含义

    >

    匹配右表中主键时间戳小于左表主键时间戳且时间戳最接近的数据行

    >=

    匹配右表中主键时间戳小于等于左表主键时间戳且时间戳最接近的数据行

    =

    匹配右表中主键时间戳等于左表主键时间戳的行

    <

    匹配右表中主键时间戳大于左表主键时间戳且时间戳最接近的数据行

    <=

    匹配右表中主键时间戳大于等于左表主键时间戳且时间戳最接近的数据行

  • 如果不含 ON 子句或 ON 子句中未指定主键列的匹配规则,则默认主键匹配规则运算符是 “>=”, 即右表中主键时戳小于等于左表主键时戳的行数据。不支持多个主连接条件;

  • ON 子句中还可以指定除主键列外的 TAG、普通列(不支持标量函数及运算)之间的等值条件用于分组计算,除此之外不支持其他类型的条件;

  • 所有 ON 条件间只支持 AND 运算;

  • JLIMIT 用于指定单行匹配结果的最大行数,可选,未指定时默认值为1,即左表每行数据最多从右表中获得一行匹配结果。JLIMIT 取值范围为 [0, 1024]。符合匹配条件的 jlimit_num 条数据不要求时间戳相同,当右表中不存在满足条件的 jlimit_num 条数据时,返回的结果行数可能小于 jlimit_num;当右表中存在符合条件的多于 jlimit_num 条数据时,如果时间戳相同将随机返回 jlimit_num 条数据。

示例

SQL 语句

查询结果

SELECT a.ts, b.ts FROM tba1 a LEFT ASOF JOIN tba2 b ON a.ts = b.ts

2023-11-17 16:29:00

2023-11-17 16:29:02

2023-11-17 16:29:03

2023-11-17 16:29:04

2023-11-17 16:29:00

NULL

2023-11-17 16:29:03

NULL

SELECT a.ts, b.ts FROM tba1 a LEFT ASOF JOIN tba2 b ON a.ts <= b.ts

2023-11-17 16:29:00

2023-11-17 16:29:02

2023-11-17 16:29:03

2023-11-17 16:29:04

2023-11-17 16:29:00

2023-11-17 16:29:03

2023-11-17 16:29:03

2023-11-17 16:29:05

SELECT a.ts, b.ts FROM tba1 a LEFT ASOF JOIN tba2 b ON a.ts > b.ts JLIMIT 2

2023-11-17 16:29:00

2023-11-17 16:29:02

2023-11-17 16:29:02

2023-11-17 16:29:03

2023-11-17 16:29:03

2023-11-17 16:29:04

2023-11-17 16:29:04

NULL

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:01

2023-11-17 16:29:03

SELECT a.ts, b.ts FROM tba1 a LEFT ASOF JOIN tba2 b

2023-11-17 16:29:00

2023-11-17 16:29:02

2023-11-17 16:29:03

2023-11-17 16:29:04

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:03

2023-11-17 16:29:03

SELECT a.ts, b.ts FROM tba1 a LEFT ASOF JOIN tba2 b JLIMIT 2

2023-11-17 16:29:00

2023-11-17 16:29:02

2023-11-17 16:29:02

2023-11-17 16:29:03

2023-11-17 16:29:03

2023-11-17 16:29:04

2023-11-17 16:29:04

2023-11-17 16:29:00

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:01

2023-11-17 16:29:03

2023-11-17 16:29:01

2023-11-17 16:29:03

3.4.6 Left Window Join

含义

左窗口连接 - 根据左表中每一行的主键时间戳和窗口边界构造窗口并据此进行窗口连接,支持窗口内进行投影、标量和聚合操作。

语法

SELECT ... FROM table_name1 LEFT WINDOW JOIN table_name2 [ON ...] WINDOW_OFFSET(start_offset, end_offset) [JLIMIT jlimit_num] [WHERE ...] [...]

结果集

左表中每一行数据与右表中基于左表主键时戳列和 WINDOW_OFFSET 划分的窗口内的至多 jlimit_num 条数据或空数据(NULL)的笛卡尔积集合 或

左表中每一行数据与右表中基于左表主键时戳列和 WINDOW_OFFSET 划分的窗口内的至多 jlimit_num 条数据的聚合结果或空数据(NULL)组成的行数据集合。

适用范围

支持超级表、普通表、子表间 Left Window Join。

说明
  • 只支持表间 Window Join,不支持子查询间 Window Join;

  • ON 子句可选,只支持指定除主键列外的 TAG、普通列(不支持标量函数及运算)之间的等值条件用于分组计算,所有条件间只支持 AND 运算;

  • WINDOW_OFFSET 用于指定窗口的左右边界相对于左表主键时间戳的偏移量,支持自带时间单位的形式,例如:WINDOW_OFFSET(-1a, 1a),表示每个窗口是 [左表主键时间戳 - 1毫秒,左表主键时间戳 + 1毫秒] ,左右边界均为闭区间。数字后面的时间单位可以是 b(纳秒)、u(微秒)、a(毫秒)、s(秒)、m(分)、h(小时)、d(天)、w(周),不支持自然月(n)、自然年(y),支持的最小时间单位为数据库精度,左右表所在数据库精度需保持一致。

  • JLIMIT 用于指定单个窗口内的最大匹配行数,可选,未指定时默认获取每个窗口内的所有匹配行。JLIMIT 取值范围为 [0, 1024],当右表中不存在满足条件的 jlimit_num 条数据时,返回的结果行数可能小于 jlimit_num;当右表中存在超过 jlimit_num 条满足条件的数据时,优先返回窗口内主键时间戳最小的 jlimit_num 条数据。

  • SQL 语句中不能含其他 GROUP BY/PARTITION BY/窗口查询;

  • 支持在 WHERE 子句中进行标量过滤,支持在 HAVING 子句中针对每个窗口进行聚合函数过滤(不支持标量过滤),不支持 SLIMIT,不支持各种窗口伪列;

示例

SQL 语句

查询结果

SELECT a.ts, b.ts FROM tba1 a LEFT WINDOW JOIN tba2 b WINDOW_OFFSET(-1s, 1s)

2023-11-17 16:29:00

2023-11-17 16:29:00

2023-11-17 16:29:02

2023-11-17 16:29:02

2023-11-17 16:29:03

2023-11-17 16:29:04

2023-11-17 16:29:04

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:01

2023-11-17 16:29:03

2023-11-17 16:29:03

2023-11-17 16:29:03

2023-11-17 16:29:05

SELECT a.ts, b.ts FROM tba1 a LEFT WINDOW JOIN tba2 b WINDOW_OFFSET(-1s, 1s) JLIMIT 1

2023-11-17 16:29:00

2023-11-17 16:29:02

2023-11-17 16:29:03

2023-11-17 16:29:04

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:03

2023-11-17 16:29:03

SELECT a.ts, count(b.*) FROM tba1 a LEFT WINDOW JOIN tba2 b WINDOW_OFFSET(-1s, 1s)

2023-11-17 16:29:00

2023-11-17 16:29:02

2023-11-17 16:29:03

2023-11-17 16:29:04

2

2

1

2

SELECT a.ts, count(b.*) FROM tba1 a LEFT WINDOW JOIN tba2 b ON a.col1 = b.col1 WINDOW_OFFSET(-1s, 1s)

2023-11-17 16:29:02

2023-11-17 16:29:04

2023-11-17 16:29:00

2023-11-17 16:29:03

1

1

0(NULL)

0(NULL)

SELECT a.ts, count(b.*) FROM tba1 a LEFT WINDOW JOIN tba2 b WINDOW_OFFSET(-1s, 1s) HAVING(count(b.*) > 1)

2023-11-17 16:29:00

2023-11-17 16:29:02

2023-11-17 16:29:04

2

2

2

3.4.7 Right Outer Join

含义

右(外)连接 - 既包含左右表同时符合连接条件的数据集合,也包括右表中不符合连接条件的数据集合。

语法

SELECT ... FROM table_name1 RIGHT [OUTER] JOIN table_name2 ON ... [WHERE ...] [...]

结果集

Inner Join 的结果集 + 右表中不符合连接条件的行和左表的空数据(NULL)组成的行数据集合。

适用范围

支持超级表、普通表、子表、子查询间 Right Join。

说明
  • OUTER 关键字可选;

示例

SQL 语句

查询结果

SELECT a.col1, b.col1 FROM sta a RIGHT JOIN sta b ON a.ts = b.ts and b.ts < '2023-11-17 16:29:02' AND a.ts < '2023-11-17 16:29:01'

1

2

1

2

NULL

NULL

NULL

NULL

NULL

NULL

1

1

2

2

3

3

4

5

5

7

3.4.8 Right Semi Join

含义

右半连接 - 通常表达的是 IN/EXISTS 的含义,即只有当左表中存在任一符合连接条件的数据时才返回右表行数据。

语法

SELECT ... FROM table_name1 RIGHT SEMI JOIN table_name2 ON ... [WHERE ...] [...]

结果集

右表中符合连接条件的行和左表任一符合连接条件的行组成的行数据集合。

适用范围

支持超级表、普通表、子表、子查询间 Right Semi Join。

示例

SQL 语句

查询结果

SELECT a.ts, b.ts FROM sta a RIGHT SEMI JOIN sta b ON a.ts = b.ts AND b.ts < '2023-11-17 16:29:02'

2023-11-17 16:29:00

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:00

2023-11-17 16:29:00

2023-11-17 16:29:01

3.4.9 Right Anti-Semi Join

含义

右反连接 - 同右半连接的逻辑正好相反,通常表达的是 NOT IN/NOT EXISTS 的含义,即只有当左表中不存在任何符合连接条件的数据时才返回右表行数据。

语法

SELECT ... FROM table_name1 RIGHT ANTI JOIN table_name2 ON ... [WHERE ...] [...]

结果集

右表中不符合连接条件的行和左表的空数据(NULL)组成的行数据集合。

适用范围

支持超级表、普通表、子表、子查询间 Right Anti-Semi Join。

示例

SQL 语句

查询结果

SELECT a.ts, b.ts FROM tba1 a RIGHT ANTI JOIN tba2 b ON a.ts = b.ts

NULL

NULL

2023-11-17 16:29:01

2023-11-17 16:29:05

3.4.10 Right ASOF Join

含义

右不完全匹配连接 - 不同于其他传统 Join 的完全匹配模式,ASOF Join 允许以指定的匹配模式进行不完全匹配,即按照主键时间戳最接近的方式进行匹配。

语法

SELECT ... FROM table_name1 RIGHT ASOF JOIN table_name2 [ON ...] [JLIMIT jlimit_num] [WHERE ...] [...]

结果集

右表中每一行数据与左表中符合连接条件的按主键列排序后时间最接近的最多 jlimit_num 条数据或空数据(NULL)的笛卡尔积集合。

适用范围

支持超级表、普通表、子表间 Right ASOF Join。

说明
  • 只支持表间 ASOF Join,不支持子查询间 ASOF Join;

  • ON 子句中支持指定主键列或主键列的 timetruncate 函数运算(不支持其他标量运算及函数)后的单个匹配规则(主连接条件),支持的运算符及其含义如下:

    运算符

    含义

    >

    匹配左表中主键时间戳大于右表主键时间戳且时间戳最接近的数据行

    >=

    匹配左表中主键时间戳大于等于右表主键时间戳且时间戳最接近的数据行

    =

    匹配左表中主键时间戳等于右表主键时间戳的行

    <

    匹配左表中主键时间戳小于右表主键时间戳且时间戳最接近的数据行

    <=

    匹配左表中主键时间戳小于等于右表主键时间戳且时间戳最接近的数据行

  • 如果不含 ON 子句或 ON 子句中未指定主键列的匹配规则,则默认主键匹配规则运算符是 “<=”, 即匹配左表中主键时间戳小于等于右表主键时间戳的行数据。不支持多个主连接条件。

  • ON 子句中还可以指定除主键列外的 TAG、普通列(不支持标量函数及运算)之间的等值条件用于分组计算,除此之外不支持其他类型的条件;

  • 所有 ON 条件间只支持 AND 运算。

  • JLIMIT 用于指定单行匹配结果的最大行数,可选,未指定时默认值为1,即右表每行数据最多从左表中获得一行匹配结果。JLIMIT 取值范围为 [0, 1024]。符合匹配条件的 jlimit_num 条数据不要求时间戳相同,当左表中不存在满足条件的 jlimit_num 条数据时,返回的结果行数可能小于 jlimit_num。

示例

SQL 语句

查询结果

SELECT a.ts, b.ts FROM tba1 a RIGHT ASOF JOIN tba2 b ON a.ts = b.ts

2023-11-17 16:29:00

NULL

2023-11-17 16:29:03

NULL

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:03

2023-11-17 16:29:05

SELECT a.ts, b.ts FROM tba1 a RIGHT ASOF JOIN tba2 b ON a.ts <= b.ts

2023-11-17 16:29:00

2023-11-17 16:29:00

2023-11-17 16:29:03

2023-11-17 16:29:04

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:03

2023-11-17 16:29:05

SELECT a.ts, b.ts FROM tba1 a RIGHT ASOF JOIN tba2 b ON a.ts > b.ts JLIMIT 2

2023-11-17 16:29:02

2023-11-17 16:29:03

2023-11-17 16:29:02

2023-11-17 16:29:03

2023-11-17 16:29:04

NULL

2023-11-17 16:29:00

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:01

2023-11-17 16:29:03

2023-11-17 16:29:05

3.4.11 Right Window Join

含义

右窗口连接 - 根据右表每一行的主键时间戳和窗口边界构造窗口并据此进行窗口连接,支持窗口内进行投影、标量和聚合操作。

语法

SELECT ... FROM table_name1 RIGHT WINDOW JOIN table_name2 [ON ...] WINDOW_OFFSET(start_offset, end_offset) [JLIMIT jlimit_num] [WHERE ...] [...]

结果集

右表中每一行数据与左表中基于右表主键时戳列和 WINDOW_OFFSET 划分的窗口内的至多 jlimit_num 条数据或空数据(NULL)的笛卡尔积集合 或

右表中每一行数据与左表中基于右表主键时戳列和 WINDOW_OFFSET 划分的窗口内的至多 jlimit_num 条数据的聚合结果或空数据(NULL)组成的行数据集合。

适用范围

支持超级表、普通表、子表间 Right Window Join。

说明
  • 只支持表间 Window Join,不支持子查询间 Window Join;

  • ON 子句可选,只支持指定除主键列外的 TAG、普通列(不支持标量函数及运算)之间的等值条件用于分组计算,所有条件间只支持 AND 运算;

  • WINDOW_OFFSET 用于指定窗口的左右边界相对于右表主键时间戳的偏移量,支持自带时间单位的形式,例如:WINDOW_OFFSET(-1a, 1a),则表示每个窗口是 [右表主键时间戳 - 1毫秒,右表主键时间戳 + 1毫秒] ,左右边界均为闭区间。数字后面的时间单位可以是 b(纳秒)、u(微秒)、a(毫秒)、s(秒)、m(分)、h(小时)、d(天)、w(周),不支持自然月、自然年,最小支持的时间单位为数据库精度,左右表所在数据库精度需保持一致。

  • JLIMIT 用于指定单个窗口内的最大匹配行数,可选,未指定时默认获取每个窗口内的所有匹配行。JLIMIT 取值范围为 [0, 1024],当左表中不存在满足条件的 jlimit_num 条数据时,返回的结果行数可能小于 jlimit_num;当左表中存在超过 jlimit_num 条满足条件的数据时,优先返回窗口内主键时间戳最小的 jlimit_num 条数据。

  • SQL 语句中不能含其他 GROUP BY/PARTITION BY/窗口查询;

  • 支持在 WHERE 子句中进行标量过滤,支持在 HAVING 子句中针对窗口进行聚合函数过滤(不支持标量过滤),不支持 SLIMIT;

示例

SQL 语句

查询结果

SELECT a.ts, b.ts FROM tba1 a RIGHT WINDOW JOIN tba2 b WINDOW_OFFSET(-1s, 1s)

2023-11-17 16:29:00

2023-11-17 16:29:00

2023-11-17 16:29:02

2023-11-17 16:29:02

2023-11-17 16:29:03

2023-11-17 16:29:04

2023-11-17 16:29:04

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:01

2023-11-17 16:29:03

2023-11-17 16:29:03

2023-11-17 16:29:03

2023-11-17 16:29:05

SELECT a.ts, b.ts FROM tba1 a RIGHT WINDOW JOIN tba2 b WINDOW_OFFSET(-1s, 1s) JLIMIT 1

2023-11-17 16:29:00

2023-11-17 16:29:00

2023-11-17 16:29:02

2023-11-17 16:29:04

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:03

2023-11-17 16:29:05

SELECT b.ts, count(a.*) FROM tba1 a RIGHT WINDOW JOIN tba2 b WINDOW_OFFSET(-1s, 1s)

2023-11-17 16:29:00

2023-11-17 16:29:01

2023-11-17 16:29:03

2023-11-17 16:29:05

1

2

3

1

SELECT b.ts, count(a.*) FROM tba1 a RIGHT WINDOW JOIN tba2 b ON a.col1 = b.col1 WINDOW_OFFSET(-1s, 1s)

2023-11-17 16:29:01

2023-11-17 16:29:03

2023-11-17 16:29:00

2023-11-17 16:29:05

1

1

0(NULL)

0(NULL)

3.4.12 Full Outer Join

含义

全(外)连接 - 既包含左右表同时符合连接条件的数据集合,也包括左右表中不符合连接条件的数据集合。

语法

SELECT ... FROM table_name1 FULL [OUTER] JOIN table_name2 ON ... [WHERE ...] [...]

结果集

Inner Join 的结果集 + 左表中不符合连接条件的行加上右表的空数据组成的行数据集合 + 右表中不符合连接条件的行加上左表的空数据组成的行数据集合。

适用范围

支持超级表、普通表、子表、子查询间 Full Outer Join。

说明
  • OUTER 关键字可选;

示例

SQL 语句

查询结果

SELECT a.ts, b.ts FROM tba1 a FULL JOIN tba2 b ON a.ts = b.ts AND a.ts < '2023-11-17 16:29:03' AND b.ts < '2023-11-17 16:29:03'

2023-11-17 16:29:00

2023-11-17 16:29:02

NULL

2023-11-17 16:29:03

2023-11-17 16:29:04

NULL

NULL

2023-11-17 16:29:00

NULL

2023-11-17 16:29:01

NULL

NULL

2023-11-17 16:29:03

2023-11-17 16:29:05

4. 限制

4.1 输入时间线限制

  • 目前所有 Join 都要求输入数据含有效的主键时间线,所有表查询都可以满足,子查询需要注意输出数据是否含有效的主键时间线。

4.2 连接条件限制

  • 除 ASOF 和 Window Join 之外,其他 Join 的连接条件中必须含主键列的主连接条件; 且

  • 主连接条件与其他连接条件间只支持 AND 运算;

  • 作为主连接条件的主键列只支持 timetruncate 函数运算(不支持其他函数和标量运算),作为其他连接条件时无限制;

4.3 分组条件限制

  • 只支持除主键列外的 TAG、普通列的等值条件;

  • 不支持标量运算;

  • 支持多个分组条件,条件间只支持 AND 运算;

4.4 查询结果顺序限制

  • 普通表、子表、子查询且无分组条件无排序的场景下,查询结果会按照驱动表的主键列顺序输出;

  • 超级表查询、Full Join或有分组条件无排序的场景下,查询结果没有固定的输出顺序;

因此,在有排序需求且输出无固定顺序的场景下,需要进行排序操作。部分依赖时间线的函数可能会因为没有有效的时间线输出而无法执行。

4.5 嵌套 Join 与多表 Join 限制

  • 目前除 Inner Join 支持嵌套与多表 Join 外,其他类型的 JoiN 暂不支持嵌套与多表 Join。

5. 总结

本次新增的 JOIN 功能,全面补充了关系型数据库中的 LEFT INNER 和 RIGHT 三种 JOIN 功能,丰富了时序数据的处理方法。

时序数据都是海量数据,JOIN 操作本身是个资源消耗大户,所以不适合在大范围内进行 JOIN 操作,推荐通过时间列限定 JOIN 操作范围,如一小时内或者一天范围内,再进行 JOIN 关联操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/35264.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

开源 - Ideal库 - Excel帮助类,ExcelHelper实现(五)

书接上回&#xff0c;我们继续来聊聊ExcelHelper的具体实现。 01、读取Excel到DataSet单元测试 在上一章我们主要讲解了读取Excel到DataSet的三个重载方法具体实现&#xff0c;还没来得及做单元测试&#xff0c;因此我们首先对这三个方法做个单元测试。具体代码如下&#xff1…

CCF-GESP 编程能力认证 C++ 七级 2024年9月份选择题详细解析

第 1 题 已知小写字母 b 的 ASCII 码为 98 &#xff0c;下列 C 代码的输出结果是&#xff08;B&#xff09;。 #include <iostream> using namespace std; int main() {char a b;a;cout << a;return 0; } A. b B. c C. 98 D. 99 【这题很简单&#xff0c;我们只…

Oceanbase离线集群部署

准备工作 两台服务器 服务器的配置参照官网要求来 服务器名配置服务器IPoceanbase116g8h192.168.10.239oceanbase216g8h192.168.10.239 这里选oceanbase1作为 obd机器 oceanbase安装包 选择社区版本的时候自己系统的安装包 ntp时间同步rpm包 联网机器下载所需的软件包 …

动手学深度学习d2l包M4芯片 gpu加速

conda创建环境 CONDA_SUBDIRosx-arm64 conda create -n ml python3.9 -c conda-forge conda env config vars set CONDA_SUBDIRosx-arm64 conda activate mlpip安装包 pip install --pre torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/n…

Y20030046 Java+JSP+SpringBoot+MYSQL+LW+实验室管理系统的设计与实现 源码

实验室管理系统 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 摘 要 伴随互联网的快速发展&#xff0c;国家对当前教育行业实行了新的改革&#xff0c;科学教育要培养更多的技术型人才&#xff0c;2020年全球爆发的新冠疫情&#xff0c;更是推动了科…

AG32 MCU与STM32 等MCU有哪些不同

STM32 MCU的特点 STM32一般是M0,M3, M4等内核的ARM Cortex内核的MCU&#xff0c;仅仅作为MCU使用&#xff0c;没有内置CPLD/FPGA的功能。 2. AG32的特点 AG32是AGM近2年来推出的差异化设计的SOC。以下我们了解以下AG32的特点。 &#xff08;1&#xff09;. 芯片结构&#xff…

【vscode】如何在项目中分享插件?

文章目录 前言一、如何获取插件名称呢&#xff1f;二、项目应用 前言 分享插件&#xff0c;除了将插件名字告诉你的小伙伴&#xff0c;当然还有其他的办法 项目根目录下创建.vscode 文件夹添加extensions.json文件 如下图 一、如何获取插件名称呢&#xff1f; 二、项目应用 …

【css】基础(一)

本专栏内容为&#xff1a;前端专栏 记录学习前端&#xff0c;分为若干个子专栏&#xff0c;html js css vue等 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;css专栏 &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &a…

Qt学习笔记第51到60讲

第51讲 记事本实现打开功能 回到第24个功能文件Notepad&#xff0c;给UI中的各个控件添加槽函数。 ①开始按钮 void Widget::on_btnOpen_clicked() {QString fileNameQFileDialog::getOpenFileName(this,tr("Open File"),"E:\\6_Qt Projects\\24_Notepad\\fi…

WPS解决Word文件引入excel对象文件无法打开提示“不能启动此对象...”的问题

一、问题现象 接收到了一份 Word文件&#xff0c;里面引入了一个Excel对象文件&#xff0c;双击时候&#xff0c;wps出现卡顿&#xff0c;过一会之后弹出错误提示&#xff1a;不能启动此对象... 二、解决方法 1.点击WPS左上角图标&#xff0c;并打开右上角设置&#xff0c;萱蕚…

# issue 8 TCP内部原理和UDP编程

TCP 通信三大步骤&#xff1a; 1 三次握手建立连接; 2 开始通信&#xff0c;进行数据交换; 3 四次挥手断开连接&#xff1b; 一、TCP内部原理--三次握手 【第一次握手】套接字A∶"你好&#xff0c;套接字B。我这儿有数据要传给你&#xff0c;建立连接吧。" 【第二次…

什么是人工智能?(Chapter 2)

Chapter 2&#xff1a; 大家到底在争论什么&#xff1f; 2022 年末&#xff0c;OpenAI 发布 ChatGPT 后不久&#xff0c;网上开始流传一个新的备忘录&#xff0c;它比其他任何东西都更能捕捉到这项技术的诡异之处。在大多数版本中&#xff0c;一个名为 "食人魔"&am…

OpenCV-平滑图像

二维卷积(图像滤波) 与一维信号一样&#xff0c;图像也可以通过各种低通滤波器&#xff08;LPF&#xff09;、高通滤波器&#xff08;HPF&#xff09;等进行过滤。LPF 有助于消除噪音、模糊图像等。HPF 滤波器有助于在图像中找到边缘。 opencv 提供了函数 **cv.filter2D()**&…

如何使用 Docker Compose 安装 Memos 自托管笔记应用

简介 Memos是一个自托管的开源笔记应用程序&#xff0c;专为个人组织和信息管理而设计。它允许用户高效地创建、存储和管理笔记&#xff0c;提供如Markdown支持、用户友好的界面和注重隐私的设计等功能。Memos可以在各种平台上运行&#xff0c;但使用Docker Compose可以简化部…

西部地区生活物资保供与城郊大仓基地高质量建设运营论坛西安市成功举办

2024 年 12 月 5日&#xff0c;由中国商业联合会、陕西省商务厅指导&#xff0c;中国商业联合会商贸物流与供应链分会、西安市发改委、西安市商务局主办&#xff0c;中企盟&#xff08;北京&#xff09;电商物流技术研究院、西安商业联合会、陕西省商贸物流供应链协会承办的“西…

[笔记] Windows 上 Git 安装详细教程:从零开始,附带每个选项解析

Git 是目前最流行的分布式版本控制系统之一&#xff0c;广泛应用于软件开发和项目管理中。对于 Windows 用户来说&#xff0c;正确安装和配置 Git 是开始使用 Git 的第一步。本文提供一份详细的指南&#xff0c;帮助你在 Windows 系统上顺利安装 Git&#xff0c;并解释每个安装…

五天SpringCloud计划——DAY3之服务治理(Nacos+OpenFeign+OKHttp)

一、引言 在微服务架构中&#xff0c;一个项目通常会被分为多个模块来降低耦合&#xff0c;但是通常情况下&#xff0c;一个项目中总会出现一种情况——一个模块内的方法需要调用另一个模块内的方法。本文就来使用NacosOpenFeignOKHttp帮助大家解决这个问题。 二、Nacos的使用…

go-blueprint create exit status 1

1. 异常信息 2024/12/06 10:59:19 Could not initialize go.mod in new project exit status 1 2024/12/06 10:59:19 Problem creating files for project. exit status 1 Error: exit status 12. 排查思路 手动进行go mod init查看手动的报错解决报错 3. 解决问题 发现是GO11…

Socket编程-tcp

1. 前言 在tcp套接字编程这里&#xff0c;我们将完成两份代码&#xff0c;一份是基于tcp实现普通的对话&#xff0c;另一份加上业务&#xff0c;client输入要执行的命令&#xff0c;server将执行结果返回给client 2. tcp_echo_server 与udp类似&#xff0c;前两步&#xff1…

Python使用Selenium自动实现表单填写之蛇年纪念币蛇钞预约(附源码,源码有注释解析,已测试可用

Python实现纪念币预约自动填写表单 声明:本文只做技术交流,不可用代码为商业用途,文末有源码下载,已测试可用。 Part 1 配置文件改写(源码 有详细的注释说明 读取配置文件,自己组数据库,录入信息 配置文件 Part 2 主函数 每一期的xpath路径都不一样 所以需要提前去网站…