本文翻译自官网:Table API https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/table/tableApi.html
Table API是用于流和批处理的统一的关系API。 Table API查询可以在批处理或流输入上运行而无需修改。 Table API是SQL语言的超集,是专门为与Apache Flink配合使用而设计的。 Table API是用于Scala和Java的语言集成的API。 Table API查询不是将查询指定为SQL常见的String值,而是以Java或Scala中的语言嵌入样式定义,并具有IDE支持,例如自动完成和语法验证。
Table API与Flink的SQL集成共享其API的许多概念和部分。 看一下Common Concepts&API,了解如何注册表或创建Table对象。 “流概念”页面讨论了流的特定概念,例如动态表和时间属性。
下面的示例假定具有属性(a,b,c,rowtime)的已注册表 Orders。 rowtime字段是流中的逻辑时间属性,或者是批处理中的常规时间戳字段。
概述与范例
Table API可用于Scala和Java。 Scala Table API利用Scala表达式,Java Table API基于已解析并转换为等效表达式的字符串。
以下示例显示了Scala和Java Table API之间的区别。 该表程序在批处理环境中执行。 它将扫描 Orders 表,按字段 a 进行分组,并计算每组的结果行。 该表程序的结果将转换为Row类型的数据集并进行打印。
通过导入org.apache.flink.api.scala._和org.apache.flink.table.api.scala._来启用Scala Table API。
以下示例显示了Scala Table API程序的构造方式。 表属性是使用Scala符号引用的,Scala符号以撇号(')开头。
import org.apache.flink.api.scala._ import org.apache.flink.table.api._ import org.apache.flink.table.api.scala._ // environment configuration val env = ExecutionEnvironment.getExecutionEnvironment val tEnv = BatchTableEnvironment.create(env) // register Orders table in table environment // ... // specify table program val orders = tEnv.scan("Orders") // schema (a, b, c, rowtime) val result = orders .groupBy('a) .select('a, 'b.count as 'cnt) .toDataSet[Row] // conversion to DataSet .print()
下一个示例显示了一个更复杂的Table API程序。 程序再次扫描 Orders
表。 它过滤空值,对String类型的字段 a 进行归一化,并针对每个小时计算并产生a平均帐单金额b。
// environment configuration // ... // specify table program val orders: Table = tEnv.scan("Orders") // schema (a, b, c, rowtime) val result: Table = orders .filter('a.isNotNull && 'b.isNotNull && 'c.isNotNull) .select('a.lowerCase() as 'a, 'b, 'rowtime) .window(Tumble over 1.hour on 'rowtime as 'hourlyWindow) .groupBy('hourlyWindow, 'a) .select('a, 'hourlyWindow.end as 'hour, 'b.avg as 'avgBillingAmount)
由于Table API是用于批处理和流数据的统一API,因此两个示例程序都可以在批处理和流输入上执行,而无需对表程序本身进行任何修改。 在这两种情况下,只要流记录不晚,程序都会产生相同的结果(有关详细信息,请参见流概念)。
Operations
Table API支持以下操作。 请注意,不是所有的操作都可以批量和流式传输。 它们被相应地标记。
Scan, Projection, and Filter
Operators | Description |
---|---|
Scan Batch Streaming |
类似于SQL查询中的FROM子句。 扫描已注册的表。
|
Select Batch Streaming |
类似于SQL SELECT语句。 执行选择操作。
您可以使用星号(*)充当通配符,选择表中的所有列。
|
As Batch Streaming |
Renames fields.
|
Where / Filter Batch Streaming |
类似于SQL WHERE子句。 过滤掉未通过过滤谓词的行。
or
|
Column Operations
Operators | Description |
---|---|
AddColumns Batch Streaming |
执行字段添加操作。 如果添加的字段已经存在,它将引发异常。
|
AddOrReplaceColumns Batch Streaming |
执行字段添加操作。 如果添加列名称与现有列名称相同,则现有字段将被替换。 此外,如果添加的字段具有重复的字段名称,则使用最后一个。
|
DropColumns Batch Streaming |
执行字段删除操作。 字段表达式应该是字段引用表达式,并且只能删除现有字段。
|
RenameColumns Batch Streaming |
执行字段重命名操作。 字段表达式应该是别名表达式,并且只能重命名现有字段。
|
Aggregations
Operators | Description |
---|---|
GroupBy Aggregation Batch Streaming Result Updating |
类似于SQL GROUP BY子句。 使用以下正在运行的聚合运算符将分组键上的行分组,以逐行聚合行。
注意:对于流式查询,根据聚合的类型和不同的分组键的数量,计算查询结果所需的状态可能会无限增长。 请提供具有有效保留间隔的查询配置,以防止出现过多的状态。 有关详细信息,请参见查询配置。 |
GroupBy Window Aggregation Batch Streaming |
在 group window 和可能的一个或多个分组键上对表进行分组和聚集。
|
Over Window Aggregation Streaming |
类似于SQL OVER子句。 基于前一行和后一行的窗口(范围),为每一行计算窗口聚合。 有关更多详细信息,请参见Windows部分。
注意:必须在同一窗口(即相同的分区,排序和范围)上定义所有聚合。 当前,仅支持PRECEDING(无边界和有界)到CURRENT ROW范围的窗口。 目前尚不支持带有FOLLOWING的范围。 必须在单个时间属性上指定ORDER BY。 |
Distinct Aggregation Batch Streaming Result Updating |
类似于SQL DISTINCT AGGREGATION子句,例如COUNT(DISTINCT a)。 不同的聚合声明聚合函数(内置或用户定义的)仅应用于不同的输入值。 可以将不同应用于GroupBy聚合,GroupBy窗口聚合和Over Window聚合。
用户定义的聚合函数也可以与DISTINCT修饰符一起使用。 要仅针对不同值计算聚合结果,只需向聚合函数添加distinct修饰符即可。
注意:对于流式查询,计算查询结果所需的状态可能会无限增长,具体取决于不同字段的数量。 请提供具有有效保留间隔的查询配置,以防止出现过多的状态。 有关详细信息,请参见查询配置。. |
Distinct Batch Streaming Result Updating |
注意:对于流式查询,计算查询结果所需的状态可能会无限增长,具体取决于不同字段的数量。 请提供具有有效保留间隔的查询配置,以防止出现过多的状态。 如果启用了状态清除功能,那么distinct必须发出消息, 以防止下游运算符过早地退出状态,这会导致distinct包含结果更新。 有关详细信息,请参见查询配置。 |
Joins
Operators | Description |
---|---|
Inner Join Batch Streaming |
类似于SQL JOIN子句。 连接两个表。 两个表必须具有不同的字段名称,并且至少一个相等的联接谓词必须通过联接运算符或使用where或filter运算符进行定义。
注意:对于流式查询,根据不同输入行的数量,计算查询结果所需的状态可能会无限增长。 请提供具有有效保留间隔的查询配置,以防止出现过多的状态。 有关详细信息,请参见查询配置。 |
Outer Join Batch StreamingResult Updating |
类似于SQL LEFT / RIGHT / FULL OUTER JOIN子句。 连接两个表。 两个表必须具有不同的字段名称,并且必须至少定义一个相等联接谓词。
注意:对于流式查询,根据不同输入行的数量,计算查询结果所需的状态可能会无限增长。 请提供具有有效保留间隔的查询配置,以防止出现过多的状态。 有关详细信息,请参见查询配置。 |
Time-windowed Join Batch Streaming |
注意:时间窗口联接是可以以流方式处理的常规联接的子集。 时间窗联接需要至少一个等联接谓词和在两侧限制时间的联接条件。 可以通过两个适当的范围谓词(<,<=,> =,>)或比较两个输入表的相同类型的时间属性(即处理时间或事件时间)的单个相等谓词来定义这种条件. 例如,以下谓词是有效的窗口连接条件:
|
Inner Join with Table Function (UDTF) Batch Streaming |
用表函数的结果联接表。 左(外)表的每一行都与表函数的相应调用产生的所有行连接在一起。 如果左表(外部)的表函数调用返回空结果,则该行将被删除。
|
Left Outer Join with Table Function (UDTF) Batch Streaming |
用表函数的结果联接表。 左(外)表的每一行都与表函数的相应调用产生的所有行连接在一起。 如果表函数调用返回空结果,则将保留对应的外部行,并用空值填充结果。 注意:当前,左外部联接的表函数的谓词只能为空或字面值true。
|
Join with Temporal Table Streaming |
时态表是跟踪其随时间变化的表。 时态表功能提供对特定时间点时态表状态的访问。 使用临时表函数联接表的语法与使用表函数进行内部联接的语法相同。 当前仅支持使用临时表的内部联接。
有关更多信息,请检查更详细的时态表概念描述。 |
Set Operations
Operators | Description |
---|---|
Union Batch |
类似于SQL UNION子句。 合并两个已删除重复记录的表,两个表必须具有相同的字段类型。
|
UnionAll Batch Streaming |
类似于SQL UNION ALL子句。 合并两个表,两个表必须具有相同的字段类型。
|
Intersect Batch |
类似于SQL INTERSECT子句。 相交返回两个表中都存在的记录。 如果一个记录在一个或两个表中多次出现,则仅返回一次,即结果表中没有重复的记录。 两个表必须具有相同的字段类型。
|
IntersectAll Batch |
类似于SQL INTERSECT ALL子句。 IntersectAll返回两个表中都存在的记录。 如果一个记录在两个表中都存在一次以上,则返回的次数与两个表中存在的次数相同,即,结果表可能具有重复的记录。 两个表必须具有相同的字段类型。
|
Minus Batch |
类似于SQL EXCEPT子句。 减号从左表返回不存在于右表中的记录。 左表中的重复记录仅返回一次,即删除了重复记录。 两个表必须具有相同的字段类型。
|
MinusAll Batch |
类似于SQL EXCEPT ALL子句。 MinusAll返回右表中不存在的记录。 将返回(n-m)次在左侧表中出现n次,在右侧表中出现m次的记录,即删除与右侧表中存在的重复项一样多的记录。 两个表必须具有相同的字段类型。
|
In Batch Streaming |
类似于SQL IN子句。 如果给定的表子查询中存在表达式,则In返回true。 子查询表必须由一列组成。 此列必须与表达式具有相同的数据类型。
注意:对于流查询,该操作将在联接和组操作中重写。 根据不同输入行的数量,计算查询结果所需的状态可能会无限增长。 请提供具有有效保留间隔的查询配置,以防止出现过多的状态。 有关详细信息,请参见查询配置。 |
OrderBy, Offset & Fetch
Operators | Description |
---|---|
Order By Batch |
|
Offset & Fetch Batch |
|
Insert
Operators | Description |
---|---|
Insert Into Batch Streaming |
与SQL查询中的INSERT INTO子句相似。 在已插入的输出表中执行插入。
|
Group Windows
Group 窗口根据时间或行计数间隔将组行聚合为有限的组,并每组评估一次聚合函数。 对于批处理表,窗口是按时间间隔对记录进行分组的便捷 shortcut 。
Windows是使用window(w:GroupWindow)子句定义的,并且需要使用as子句指定的别名。 为了按窗口对表进行分组,必须像常规分组属性一样在groupBy(...)子句中引用窗口别名。 以下示例显示如何在表上定义窗口聚合。
val table = input
.window([w: GroupWindow] as 'w) // define window with alias w
.groupBy('w) // group the table by window w
.select('b.sum) // aggregate
在流式传输环境中,如果窗口聚合除对窗口进行分组以外,还对一个或多个属性进行分组,则它们只能并行计算,即groupBy(...)子句引用窗口别名和至少一个其他属性。 仅引用窗口别名的groupBy(...)子句(例如上例中的子句)只能由单个非并行任务求值。 以下示例显示如何使用其他分组属性定义窗口聚合。
val table = input .window([w: GroupWindow] as 'w) // define window with alias w .groupBy('w, 'a) // group the table by attribute a and window w .select('a, 'b.sum) // aggregate
可以在select语句中将窗口属性(例如时间窗口的开始,结束或行时间时间戳)添加为窗口别名的属性,分别为w.start,w.end和w.rowtime。 窗口开始和行时间时间戳是包含窗口的上下边界。 相反,窗口结束时间戳是唯一的窗口上边界。 例如,从下午2点开始的30分钟滚动窗口将以14:00:00.000作为开始时间戳,以14:29:59.999作为行时间时间戳,以14:30:00.000作为结束时间戳。
val table = input .window([w: GroupWindow] as 'w) // define window with alias w .groupBy('w, 'a) // group the table by attribute a and window w .select('a, 'w.start, 'w.end, 'w.rowtime, 'b.count) // aggregate and add window start, end, and rowtime timestamps
Window参数定义行如何映射到窗口。 窗口不是用户可以实现的接口。 相反,Table API提供了一组具有特定语义的预定义Window类,这些类被转换为基础的DataStream或DataSet操作。 支持的窗口定义在下面列出。
Tumble (Tumbling Windows)
滚动窗口将行分配给固定长度的非重叠连续窗口。 例如,5分钟的滚动窗口以5分钟为间隔对行进行分组。 可以在事件时间,处理时间或行数上定义滚动窗口。
滚动窗口是使用Tumble类定义的,如下所示:
Method | Description |
---|---|
over |
将窗口的长度定义为时间或行计数间隔。 |
on |
用于分组(时间间隔)或排序(行计数)的时间属性。 对于批查询,它可以是任何Long或Timestamp属性。 对于流查询,它必须是声明的事件时间或处理时间时间属性。 |
as |
为窗口分配别名。 别名用于引用以下groupBy()子句中的窗口,并可以选择在select()子句中选择窗口属性,例如窗口开始,结束或行时间时间戳。 |
// Tumbling Event-time Window .window(Tumble over 10.minutes on 'rowtime as 'w) // Tumbling Processing-time Window (assuming a processing-time attribute "proctime") .window(Tumble over 10.minutes on 'proctime as 'w) // Tumbling Row-count Window (assuming a processing-time attribute "proctime") .window(Tumble over 10.rows on 'proctime as 'w)
Slide (Sliding Windows)
滑动窗口的大小固定,并以指定的滑动间隔滑动。 如果滑动间隔小于窗口大小,则滑动窗口重叠。 因此,可以将行分配给多个窗口。 例如,一个15分钟大小的滑动窗口和5分钟的滑动间隔将每行分配给3个15分钟大小的不同窗口,它们以5分钟的间隔进行评估。 可以在事件时间,处理时间或行数上定义滑动窗口。
滑动窗口是通过使用Slide类定义的,如下所示:
Method | Description |
---|---|
over |
将窗口的长度定义为时间或行计数间隔。 |
every |
将幻灯片间隔定义为时间间隔或行计数间隔。 滑动间隔必须与尺寸间隔具有相同的类型。 |
on |
用于分组(时间间隔)或排序(行计数)的时间属性。 对于批查询,它可以是任何Long或Timestamp属性。 对于流查询,它必须是声明的事件时间或处理时间时间属性。 |
as |
为窗口分配别名。 别名用于引用以下groupBy()子句中的窗口,并可以选择在select()子句中选择窗口属性,例如窗口开始,结束或行时间时间戳。 |
// Sliding Event-time Window .window(Slide over 10.minutes every 5.minutes on 'rowtime as 'w) // Sliding Processing-time window (assuming a processing-time attribute "proctime") .window(Slide over 10.minutes every 5.minutes on 'proctime as 'w) // Sliding Row-count window (assuming a processing-time attribute "proctime") .window(Slide over 10.rows every 5.rows on 'proctime as 'w)
Session (Session Windows)
会话窗口没有固定的大小,但其边界由不活动的时间间隔定义,即,如果在定义的间隔时间段内未出现任何事件,则会话窗口关闭。 例如,间隔30分钟的会话窗口在30分钟不活动后观察到一行时开始(否则该行将被添加到现有窗口),如果在30分钟内未添加任何行,则关闭该窗口。 会话窗口可以在事件时间或处理时间工作。
通过使用Session类定义会话窗口,如下所示:
Method | Description |
---|---|
withGap |
将两个窗口之间的间隔定义为时间间隔。 |
on |
用于分组(时间间隔)或排序(行计数)的时间属性。 对于批查询,它可以是任何Long或Timestamp属性。 对于流查询,它必须是声明的事件时间或处理时间时间属性。 |
as |
为窗口分配别名。 别名用于引用以下groupBy()子句中的窗口,并可以选择在select()子句中选择窗口属性,例如窗口开始,结束或行时间时间戳。 |
// Session Event-time Window .window(Session withGap 10.minutes on 'rowtime as 'w) // Session Processing-time Window (assuming a processing-time attribute "proctime") .window(Session withGap 10.minutes on 'proctime as 'w)
Over Windows
窗口聚合是标准SQL(OVER子句)已知的,并在查询的SELECT子句中定义。 与在GROUP BY子句中指定的组窗口不同,在窗口上方不会折叠行。 取而代之的是,在窗口聚合中,为每个输入行在其相邻行的范围内计算一个聚合。
使用window(w:OverWindow *)子句(在Python API中使用over_window(* OverWindow))定义窗口,并在select()方法中通过别名引用。 以下示例显示了如何在表上定义窗口聚合。
val table = input
.window([w: OverWindow] as 'w) // define over window with alias w
.select('a, 'b.sum over 'w, 'c.min over 'w) // aggregate over the over window w
OverWindow定义了计算聚合的行范围。 OverWindow不是用户可以实现的接口。 相反,Table API提供了Over类来配置over窗口的属性。 可以在事件时间或处理时间以及指定为时间间隔或行计数的范围上定义窗口上方。 受支持的over窗口定义作为Over(和其他类)上的方法公开,并在下面列出:
Method | Required | Description |
---|---|---|
partitionBy |
Optional |
在一个或多个属性上定义输入的分区。 每个分区都经过单独排序,并且聚合函数分别应用于每个分区。 注意:在流环境中,仅当窗口包含partition by子句时,才可以并行计算整个窗口聚合。 没有partitionBy(...),流将由单个非并行任务处理。 |
orderBy |
Required |
定义每个分区内的行顺序,从而定义将聚合函数应用于行的顺序。 注意:对于流查询,它必须是声明的事件时间或处理时间时间属性。 当前,仅支持单个sort属性。 |
preceding |
Optional |
定义窗口中包含的并在当前行之前的行的间隔。 该间隔可以指定为时间间隔或行计数间隔。 用时间间隔的大小指定窗口上的边界,例如,时间间隔为10分钟,行计数间隔为10行。 使用常数来指定窗口上的无边界,即对于时间间隔为UNBOUNDED_RANGE或对于行计数间隔为UNBOUNDED_ROW。 Windows上的无边界从分区的第一行开始。 如果省略了前面的子句,则将UNBOUNDED_RANGE和CURRENT_RANGE用作窗口的默认前后
|
following |
Optional |
定义窗口中包含并紧随当前行的行的窗口间隔。 该间隔必须与前面的间隔(时间或行计数)以相同的单位指定。 目前,不支持具有当前行之后的行的窗口。 相反,您可以指定两个常量之一:
|
as |
Required |
为上方窗口分配别名。 别名用于引用以下select()子句中的over窗口。 |
注意:当前,同一select()调用中的所有聚合函数必须在相同的窗口范围内计算。
Unbounded Over Windows
// Unbounded Event-time over window (assuming an event-time attribute "rowtime") .window(Over partitionBy 'a orderBy 'rowtime preceding UNBOUNDED_RANGE as 'w) // Unbounded Processing-time over window (assuming a processing-time attribute "proctime") .window(Over partitionBy 'a orderBy 'proctime preceding UNBOUNDED_RANGE as 'w) // Unbounded Event-time Row-count over window (assuming an event-time attribute "rowtime") .window(Over partitionBy 'a orderBy 'rowtime preceding UNBOUNDED_ROW as 'w) // Unbounded Processing-time Row-count over window (assuming a processing-time attribute "proctime") .window(Over partitionBy 'a orderBy 'proctime preceding UNBOUNDED_ROW as 'w)
Bounded Over Windows
// Bounded Event-time over window (assuming an event-time attribute "rowtime") .window(Over partitionBy 'a orderBy 'rowtime preceding 1.minutes as 'w) // Bounded Processing-time over window (assuming a processing-time attribute "proctime") .window(Over partitionBy 'a orderBy 'proctime preceding 1.minutes as 'w) // Bounded Event-time Row-count over window (assuming an event-time attribute "rowtime") .window(Over partitionBy 'a orderBy 'rowtime preceding 10.rows as 'w) // Bounded Processing-time Row-count over window (assuming a processing-time attribute "proctime") .window(Over partitionBy 'a orderBy 'proctime preceding 10.rows as 'w)
Row-based Operations
基于行的操作生成具有多列的输出。
Operators | Description |
---|---|
Map Batch Streaming |
使用用户定义的标量函数或内置标量函数执行映射操作。 如果输出类型是复合类型,则输出将被展平.
|
FlatMap Batch Streaming |
使用表格功能执行flatMap操作.
|
Aggregate Batch StreamingResult Updating |
使用聚合函数执行聚合操作。 您必须使用select语句关闭“聚合”,并且select语句不支持聚合功能。 如果输出类型是复合类型,则聚合的输出将被展平.
|
Group Window Aggregate Batch Streaming |
在组窗口和可能的一个或多个分组键上对表进行分组和聚集。 您必须使用select语句关闭“聚合”。 并且select语句不支持“ *”或聚合函数.
|
FlatAggregate Streaming Result Updating |
类似于GroupBy聚合。 使用以下运行表聚合运算符将分组键上的行分组,以逐行聚合行。 与AggregateFunction的区别在于TableAggregateFunction可以为一个组返回0个或更多记录。 您必须使用select语句关闭“ flatAggregate”。 并且select语句不支持聚合函数. 除了使用emitValue输出结果外,还可以使用emitUpdateWithRetract方法。 与emittValue不同,emitUpdateWithRetract用于发出已更新的值。 此方法在撤消模式下增量输出数据,即,一旦有更新,我们就必须在发送新的更新记录之前撤回旧记录。 如果在表聚合函数中定义了这两种方法,则将优先使用emitUpdateWithRetract方法,因为这两种方法比emitValue更有效,因为它可以增量输出值。 有关详细信息,请参见表聚合函数。
Note: 对于流查询,根据聚合类型和不同的分组键的数量,计算查询结果所需的状态可能会无限增长。 请提供具有有效保留间隔的查询配置,以防止出现过多的状态。 有关详细信息,请参见查询配置。 |
Group Window FlatAggregate Streaming |
在组窗口和可能的一个或多个分组键上对表进行分组和聚集。 您必须使用select语句关闭“ flatAggregate”。 并且select语句不支持聚合函数.
|
Data Types
请参阅有关数据类型的专用页面。
通用类型和(嵌套的)复合类型(例如POJO,元组,行,Scala case class)也可以是一行的字段。
可以使用值访问功能访问具有任意嵌套的复合类型的字段。
泛型类型被视为黑盒,可以通过用户定义的函数传递或处理。
Expression Syntax
上一节中的某些运算符期望一个或多个表达式。 可以使用嵌入式Scala DSL或字符串指定表达式。 请参考上面的示例以了解如何指定表达式。
这是用于表达式的EBNF语法:
expressionList = expression , { "," , expression } ; expression = overConstant | alias ; alias = logic | ( logic , "as" , fieldReference ) | ( logic , "as" , "(" , fieldReference , { "," , fieldReference } , ")" ) ; logic = comparison , [ ( "&&" | "||" ) , comparison ] ; comparison = term , [ ( "=" | "==" | "===" | "!=" | "!==" | ">" | ">=" | "<" | "<=" ) , term ] ; term = product , [ ( "+" | "-" ) , product ] ; product = unary , [ ( "*" | "/" | "%") , unary ] ; unary = [ "!" | "-" | "+" ] , composite ; composite = over | suffixed | nullLiteral | prefixed | atom ; suffixed = interval | suffixAs | suffixCast | suffixIf | suffixDistinct | suffixFunctionCall | timeIndicator ; prefixed = prefixAs | prefixCast | prefixIf | prefixDistinct | prefixFunctionCall ; interval = timeInterval | rowInterval ; timeInterval = composite , "." , ("year" | "years" | "quarter" | "quarters" | "month" | "months" | "week" | "weeks" | "day" | "days" | "hour" | "hours" | "minute" | "minutes" | "second" | "seconds" | "milli" | "millis") ; rowInterval = composite , "." , "rows" ; suffixCast = composite , ".cast(" , dataType , ")" ; prefixCast = "cast(" , expression , dataType , ")" ; dataType = "BYTE" | "SHORT" | "INT" | "LONG" | "FLOAT" | "DOUBLE" | "BOOLEAN" | "STRING" | "DECIMAL" | "SQL_DATE" | "SQL_TIME" | "SQL_TIMESTAMP" | "INTERVAL_MONTHS" | "INTERVAL_MILLIS" | ( "MAP" , "(" , dataType , "," , dataType , ")" ) | ( "PRIMITIVE_ARRAY" , "(" , dataType , ")" ) | ( "OBJECT_ARRAY" , "(" , dataType , ")" ) ; suffixAs = composite , ".as(" , fieldReference , ")" ; prefixAs = "as(" , expression, fieldReference , ")" ; suffixIf = composite , ".?(" , expression , "," , expression , ")" ; prefixIf = "?(" , expression , "," , expression , "," , expression , ")" ; suffixDistinct = composite , "distinct.()" ; prefixDistinct = functionIdentifier , ".distinct" , [ "(" , [ expression , { "," , expression } ] , ")" ] ; suffixFunctionCall = composite , "." , functionIdentifier , [ "(" , [ expression , { "," , expression } ] , ")" ] ; prefixFunctionCall = functionIdentifier , [ "(" , [ expression , { "," , expression } ] , ")" ] ; atom = ( "(" , expression , ")" ) | literal | fieldReference ; fieldReference = "*" | identifier ; nullLiteral = "nullOf(" , dataType , ")" ; timeIntervalUnit = "YEAR" | "YEAR_TO_MONTH" | "MONTH" | "QUARTER" | "WEEK" | "DAY" | "DAY_TO_HOUR" | "DAY_TO_MINUTE" | "DAY_TO_SECOND" | "HOUR" | "HOUR_TO_MINUTE" | "HOUR_TO_SECOND" | "MINUTE" | "MINUTE_TO_SECOND" | "SECOND" ; timePointUnit = "YEAR" | "MONTH" | "DAY" | "HOUR" | "MINUTE" | "SECOND" | "QUARTER" | "WEEK" | "MILLISECOND" | "MICROSECOND" ; over = composite , "over" , fieldReference ; overConstant = "current_row" | "current_range" | "unbounded_row" | "unbounded_row" ; timeIndicator = fieldReference , "." , ( "proctime" | "rowtime" ) ;
Literals: 在这里,文字是有效的Java文字。 字符串文字可以使用单引号或双引号指定。 复制引号以进行转义(例如,'It''s me.' or "I ""like"" dogs.")。
Null literals: 空文字必须附加一个类型。 使用nullOf(type)(例如nullOf(INT))创建空值。
Field references: fieldReference指定数据中的一列(如果使用*,则指定所有列),而functionIdentifier指定受支持的标量函数。 列名和函数名遵循Java标识符语法。
Function calls: 指定为字符串的表达式也可以使用前缀表示法而不是后缀表示法来调用运算符和函数。
Decimals: 如果需要使用精确的数值或大的十进制数,则Table API还支持Java的BigDecimal类型。 在Scala Table API中,小数可以由BigDecimal(“ 123456”)定义,而在Java中,可以通过附加“ p”来精确定义例如 123456p
Time representation: 为了使用时间值,Table API支持Java SQL的日期,时间和时间戳类型。 在Scala Table API中,可以使用java.sql.Date.valueOf(“ 2016-06-27”),java.sql.Time.valueOf(“ 10:10:42”)或java.sql定义文字。 Timestamp.valueOf(“ 2016-06-27 10:10:42.123”)。 Java和Scala表API还支持调用“ 2016-06-27” .toDate(),“ 10:10:42” .toTime()和“ 2016-06-27 10:10:42.123” .toTimestamp() 用于将字符串转换为时间类型。 注意:由于Java的时态SQL类型取决于时区,因此请确保Flink Client和所有TaskManager使用相同的时区。
Temporal intervals: 时间间隔可以表示为月数(Types.INTERVAL_MONTHS)或毫秒数(Types.INTERVAL_MILLIS)。 可以添加或减去相同类型的间隔(例如1.小时+ 10分钟)。 可以将毫秒间隔添加到时间点(例如“ 2016-08-10” .toDate + 5.days)。
Scala expressions: Scala表达式使用隐式转换。 因此,请确保将通配符导入org.apache.flink.table.api.scala._添加到程序中。 如果文字不被视为表达式,请使用.toExpr(如3.toExpr)强制转换文字。
欢迎关注Flink菜鸟公众号,会不定期更新Flink(开发技术)相关的推文
注意:在流环境中,仅当窗口包含partition by子句时,才可以并行计算整个窗口聚合。 没有partitionBy(...),流将由单个非并行任务处理。