Apache Calcite官方文档中文版- 进阶-3( 四 )


Apache Calcite官方文档中文版- 进阶-3

文章插图
但是这个流只包含几条记录,而不是一个小时的汇总 。我们需要对流的历史记录运行一个关系查询:
SELECT productId, count(*)FROM OrdersWHERE rowtime BETWEEN current_timestamp - INTERVAL '1' HOURAND current_timestamp;
如果流的历史记录正在滚动到表中,尽管成本很高,我们可以回答查询 。更好的办法是,如果我们可以告诉系统将一小时的汇总转化为表格,在流式处理过程中不断维护它,并自动重写查询以使用表格 。
3.14 排序
ORDER BY的故事类似于GROUP BY 。语法看起来像普通的SQL,但是必须确保它能够提供及时的结果 。因此,它需要在ORDER BY键的前沿( edge)有一个单调的表达式 。
SELECT STREAM CEIL(rowtime TO hour) AS rowtime, productId, orderId, unitsFROM OrdersORDER BY CEIL(rowtime TO hour) ASC, units DESC;rowtime | productId | orderId | units----------+-----------+---------+-------10:00:00 |30 |8 |2010:00:00 |30 |5 |410:00:00 |20 |7 |210:00:00 |10 |6 |111:00:00 |40 |11 |1211:00:00 |10 |9 |611:00:00 |10 |12 |411:00:00 |10 |10 |1
大多数查询将按照插入的顺序返回结果,因为引使用流式算法,但不应该依赖它 。例如,考虑一下:
SELECT STREAM *FROM OrdersWHERE productId = 10UNION ALLSELECT STREAM *FROM OrdersWHERE productId = 30;rowtime | productId | orderId | units----------+-----------+---------+-------10:17:05 |10 |6 |110:17:00 |30 |5 |410:18:07 |30 |8 |2011:02:00 |10 |9 |611:04:00 |10 |10 |111:24:11 |10 |12 |4
= 30的行显然是不符合order要求的,可能是因为流以分区,分区后的流在不同的时间发送了他们的数据 。
如果您需要特定的顺序,请添加一个显式的ORDER BY:
可能会通过合并使用实现UNION ALL,这样只是效率稍微低些 。
只需要添加一个ORDER BY到最外层的查询 。如果需要在UNION ALL之后执行GROUP BY,将会隐式添加ORDER BY,以便使GROUP BY算法成为可能 。
3.15 表格构造器
子句创建一个拥有给定行集合的内联表 。
流式传输是不允许的 。这组行不会发生改变,因此一个流永远不会返回任何行 。
> SELECT STREAM * FROM (VALUES (1, 'abc'));ERROR: Cannot stream VALUES
3.16 滑动窗口
标准SQL的功能特性之一可以在子句中使用所谓的“分析函数” 。不像GROUP BY,不会折叠记录 。对于每个进来的记录,出来一个记录 。但是聚合函数是基于一个多行的窗口 。
我们来看一个例子 。
SELECT STREAM rowtime,productId,units,SUM(units) OVER (ORDER BY rowtime RANGE INTERVAL '1' HOUR PRECEDING) unitsLastHour
这个功能特性付出很小的努力就包含了很多Power 。在子句中可以有多个函数,基于多个窗口规则定义 。
以下示例返回在过去10分钟内平均订单数量大于上周平均订单数量的订单 。
SELECT STREAM *FROM (SELECT STREAM rowtime,productId,units,AVG(units) OVER product (RANGE INTERVAL '10' MINUTE PRECEDING) AS m10,AVG(units) OVER product (RANGE INTERVAL '7' DAY PRECEDING) AS d7FROM OrdersWINDOW product AS (ORDER BY rowtimePARTITION BY productId))
为了简洁起见,在这里我们使用一种语法,其中使用子句部分定义窗口,然后在每个OVER子句中细化窗口 。也可以定义子句中的所有窗口,或者如果您愿意,可以定义所有内联窗口 。
但真正的power超越语法 。在幕后,这个查询维护着两个表,并且使用FIFO队列添加和删除子汇总中的值 。但是,无需在查询中引入联接,也可以访问这些表 。
窗口化聚合语法的一些其他功能特性:
我记得一些计划器的元数据(成本指标):