Skip to main content

时间过滤器

时间过滤器(Temporal fliter)允许您基于时间间隔过滤数据,通常用于检索特定时间范围内的数据。有了它,您就可以基于特定时间过滤数据,如当前时间、特定日期或日期范围。通过使用时间过滤器,您可以确保您的查询只返回您感兴趣的时期的相关数据,使您的数据分析更加准确和高效。

句法

一个有效的时间过滤器包括以下组成部分:

  • 比较运算符,包括 <><=>==BETWEEN
  • 以涉及基 Relation 中列的时间表达式作为左侧
  • NOW() +/- interval 作为右侧的时间表达式

时间过滤器条件不能使用 OR 运算符与另一个时间过滤器连接,但可以与普通表达式连接。请参见下面的例子:

-- 允许
t > NOW() - INTERVAL '1 hour' OR t IS NULL OR a < 1

-- 无效
t > NOW() - INTERVAL '1 hour' OR t < NOW() - INTERVAL '1 hour'

-- 无效
(a < 1) OR (t > NOW() - INTERVAL '1 hour' AND t < NOW() - INTERVAL '1')

此外,时间过滤器条件不能使用 AND 运算符与包含时间过滤器的表达式连接。例子如下:

-- 无效
(t > NOW() - INTERVAL '1 hour' OR t is NULL OR a < 1)
AND (t < NOW() - INTERVAL '1 hour' OR a < 1)

用法 1:删除和清理过期数据

NOW() 与时间表达式作为基 Relation 的下界条件时,如 t > NOW() - INTERVAL '1 hour',它可以过滤掉事件时间太旧的记录。

以下查询返回 sales 表过去一周内的所有销售记录。

SELECT * 
FROM sales
WHERE sale_date > NOW() - INTERVAL '1 week';

此查询中的时间过滤器是 sale_date > NOW() - INTERVAL '1 week'。它基于 sale_date 列过滤行,并检查它是否在当前时间的一周内,或 NOW() 的一周内。

以下查询返回 user_sessions 表中, 将last_active 时间戳加上两倍session_timeout后,其和大于当前时间戳的所有行,这些数据属于会话处于活动状态的用户。此查询可用于从数据库中清理旧的用户会话,删除不再满足条件的任何行。

SELECT * 
FROM user_sessions
WHERE last_active + session_timeout * 2 > NOW();

此查询中的时间过滤器位于 WHERE 子句中。它检查最后活动的时间戳加上两倍会话超时是否大于当前时间或 NOW()。这表明会话仍处于活动状态。

用法 2:延迟表变更

NOW() 与时间表达式作为基 Relation 的上界条件时,如 ts + interval '1 hour' < now(),它可以“延迟”输入了 Relation 的表变更。当与时间 Join一起使用时,这可能很有用。

以下一个使用时间 Join 扩展表的典型例子。

  CREATE SOURCE fact(id1 INT, a1 INT, p_time TIMESTAMPTZ AS proctime()) WITH (connector = 'kafka', ...);
CREATE TABLE dimension(id2 INT, a2 INT, PRIMARY KEY (id2)) WITH (connector = 'jdbc', ...);
CREATE MATERIALIZED VIEW mv AS SELECT id1, a1, a2 FROM fact LEFT JOIN dimension FOR SYSTEM_TIME AS OF PROCTIME() ON id1 = id2;

然而,在上述例子中,由于网络或其他阶段的延迟,我们并不能保证 fact 的记录到达时,dimension 表中相应的记录已经到达。于是,我们可以在 fact 源上设置时间过滤器以引入延迟并等待维度表的变更。

  CREATE MATERIALIZED VIEW mv AS 
SELECT
id1, a1, a2
FROM (
-- 将源延迟 5 秒
SELECT * FROM fact WHERE fact.p_time + INTERVAL '5' SECOND < NOW()
) fact
LEFT JOIN dimension FOR SYSTEM_TIME AS OF PROCTIME() ON id1 = id2;
note

当前,RisingWave 的优化器不能确保时间过滤器能条件下推。请像 SQL 示例中那样,将时间过滤器作为一个子查询添加到 FROM 子句中,而不是将时间过滤器写在查询的顶层 WHERE 子句中。

info

示例中的 PROCTIME 可以替换为记录中的事件时间。