当前位置: 首页 > news >正文

TDengine 中 InterP 函数用户手册

在这里插入图片描述

TDengine INTERP 函数用户使用手册

1. 概述

1.1 功能介绍

INTERP 函数是 TDengine 中用于数据插值的重要函数,主要用于在时间序列数据中进行数据插值和填充。该函数可以根据指定的时间点和插值方法,计算出对应时间点的数据值。

1.2 应用场景

在工业物联网、智能电表、传感器监控等场景中,经常遇到以下问题:

  • 数据采集不均匀,存在时间间隔
  • 需要在特定时间点获取数据值
  • 数据缺失需要进行合理的估算
  • 需要将不同采样频率的数据统一到相同的时间刻度

2. 函数语法

INTERP(expr [, ignore_null_values]) [RANGE(timestamp1, timestamp2) EVERY(interval) [FILL(fill_mode)]]

2.1 参数说明

  • expr: 要进行插值的表达式,通常是列名
  • ignore_null_values: 可选参数,值为 0 或 1
    • 0: 不忽略 NULL 值(默认)
    • 1: 忽略 NULL 值
  • RANGE: 指定插值的时间范围
    • timestamp1: 起始时间
    • timestamp2: 结束时间
    • 支持时间范围扩展:RANGE('2023-01-01 00:00:00', 10s) 表示在时间点前后 10s 范围内查找数据
  • EVERY: 指定插值的时间间隔
    • interval: 时间间隔,如 1a(毫秒)、1s(秒)、1m(分)、1h(小时)、1d(天)、1w(周)
  • FILL: 指定填充模式
    • NULL: 使用 NULL 填充(默认)
    • VALUE: 使用指定值填充
    • PREV: 使用前一个值填充
    • NEXT: 使用后一个值填充
    • LINEAR: 线性插值
    • NONE: 不填充
    • NEAR: 使用距离当前时间点最近的数据进行插值(v3.3.4.9+)

2.2 返回数据类型

返回数据类型与字段类型相同。

2.3 适用数据类型

主要适用于数值类型数据。

2.4 适用范围

适用于表和超级表查询。

2.5 重要使用说明

  1. 专用语法: INTERP 函数使用专用的 interp 子句语法,当 SQL 语句中存在 interp 子句时,只能查询 INTERP 函数,不能与其他函数一起查询
  2. 语法限制: interp 子句与窗口子句(window_clause)、分组子句(group_by_clause)不能同时使用
  3. 必要组合: INTERP 函数需要与 RANGE、EVERY 和 FILL 子句一起使用;流计算不支持使用 RANGE,但需要与 EVERY 和 FILL 关键字一起使用
  4. 时间范围: RANGE(timestamp1, timestamp2) 需满足 timestamp1 <= timestamp2
  5. 单点插值: 可以在 RANGE 字段中只指定唯一的时间戳对单个时间点进行插值,此时 EVERY 字段可以省略
  6. 超级表处理: 作用于超级表时,会将该超级表下的所有子表数据按照主键列排序后进行插值计算,也可以搭配 PARTITION BY tbname 使用
  7. FILL 行为: 在 FILL PREV/NEXT/NEAR 时,当截面存在数据时不会进行 FILL,即便当前值为 NULL
  8. 复合主键: 对于带复合主键的表,若存在相同时间戳的数据,则只有对应的复合主键最小的数据参与运算

2.6 特殊伪列支持

  • _irowts: 返回插值点所对应的时间戳(v3.0.2.0+)
  • _isfilled: 显示返回结果是否为原始记录或插值算法产生的数据(v3.0.3.0+)
  • _irowts_origin: 仅在 FILL PREV/NEXT/NEAR 模式时可用,返回 interp 函数所使用的原始数据的时间戳列(v3.3.4.9+)

3. 主要使用场景

3.1 智能电表数据插值

场景描述

智能电表数据采集可能存在网络中断或设备故障导致的数据缺失,需要进行数据插值以保证数据的连续性。

示例代码
-- 场景1:电压数据线性插值
-- 在过去1小时内,每分钟插值一次电压数据
SELECT ts,INTERP(电压) 
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(LINEAR);-- 场景2:功率数据前值填充,忽略NULL值
-- 每30秒插值一次功率数据,使用前一个值填充,忽略NULL值
SELECT ts,INTERP(功率, 1) 
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:00:00', '2024-01-01 12:00:00') 
EVERY(30s) 
FILL(PREV);-- 场景3:单点插值
-- 在特定时间点进行插值,不需要EVERY子句
SELECT ts,INTERP(电压) 
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:30:00') 
FILL(LINEAR);-- 场景4:使用伪列获取插值信息
-- 获取插值结果并显示是否为插值数据
SELECT ts,INTERP(电压) AS 电压值,_isfilled AS 是否插值,_irowts AS 插值时间戳
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(LINEAR);

3.2 传感器数据同步

场景描述

不同传感器的采样频率可能不同,需要将它们统一到相同的时间刻度进行对比分析。

示例代码
-- 场景3:多相电流数据同步
-- 将三相电流数据统一到每10秒一个采样点
SELECT ts,INTERP(电流_A相) AS 电流_A,INTERP(电流_B相) AS 电流_B,INTERP(电流_C相) AS 电流_C
FROM tdasset.vt_em-7 
RANGE('2024-01-01 09:00:00', '2024-01-01 10:00:00') 
EVERY(10s) 
FILL(LINEAR);-- 场景4:温度和湿度数据对齐
-- 将温度和湿度数据对齐到相同的时间点
SELECT ts,INTERP(温度) AS 温度值,INTERP(湿度) AS 湿度值
FROM sensor_data 
RANGE('2024-01-01 08:00:00', '2024-01-01 16:00:00') 
EVERY(5m) 
FILL(LINEAR);

3.3 数据质量检测

场景描述

通过插值可以检测数据的异常值和缺失情况,用于数据质量评估。

示例代码
-- 场景5:电压异常检测
-- 通过插值检测电压数据的连续性
SELECT ts,INTERP(电压) AS 插值电压,ABS(电压 - INTERP(电压)) AS 偏差值
FROM tdasset.vt_em-6 
RANGE('2024-01-01 00:00:00', '2024-01-01 23:59:59') 
EVERY(1m) 
FILL(LINEAR)
WHERE ABS(电压 - INTERP(电压)) > 10;-- 场景6:功率数据完整性检查
-- 检查功率数据的缺失情况
SELECT ts,INTERP(功率) AS 插值功率,CASE WHEN INTERP(功率) IS NULL THEN '数据缺失'ELSE '数据正常'END AS 数据状态
FROM tdasset.vt_em-6 
RANGE('2024-01-01 00:00:00', '2024-01-02 00:00:00') 
EVERY(1m) 
FILL(NULL);

3.4 报表生成

场景描述

生成定时报表时,需要在固定的时间点获取数据值,即使原始数据不在这些时间点。

示例代码
-- 场景7:小时报表数据生成
-- 生成每小时整点的电表数据报表
SELECT ts AS 报表时间,INTERP(电压) AS 小时电压,INTERP(电流) AS 小时电流,INTERP(功率) AS 小时功率
FROM tdasset.vt_em-6 
RANGE('2024-01-01 00:00:00', '2024-01-01 23:59:59') 
EVERY(1h) 
FILL(LINEAR);-- 场景8:日报表数据汇总
-- 生成每日8点的电表数据快照
SELECT ts AS 日期,INTERP(电压) AS 日电压,INTERP(累计用电量) AS 日用电量
FROM tdasset.vt_em-6 
RANGE('2024-01-01 08:00:00', '2024-01-31 08:00:00') 
EVERY(1d) 
FILL(PREV);

3.5 实时监控告警

场景描述

在实时监控系统中,需要在特定时间点检查设备状态,触发告警。

示例代码
-- 场景9:实时电压监控
-- 每分钟检查电压是否超过阈值
SELECT ts,INTERP(电压) AS 当前电压,CASE WHEN INTERP(电压) > 250 THEN '电压过高告警'WHEN INTERP(电压) < 200 THEN '电压过低告警'ELSE '电压正常'END AS 告警状态
FROM tdasset.vt_em-6 
RANGE(NOW() - INTERVAL 1 HOUR, NOW()) 
EVERY(1m) 
FILL(LINEAR);-- 场景10:设备连接状态检查
-- 每30秒检查设备是否有数据上报
SELECT ts,INTERP(电流) AS 电流值,CASE WHEN INTERP(电流) IS NULL THEN '设备离线'ELSE '设备在线'END AS 连接状态
FROM tdasset.vt_em-6 
RANGE(NOW() - INTERVAL 10 MINUTES, NOW()) 
EVERY(30s) 
FILL(NULL);

4. 填充模式详解

4.1 LINEAR(线性插值)

适用于连续变化的数据,如温度、电压等。

-- 线性插值示例
SELECT ts,INTERP(温度) AS 插值温度
FROM sensor_data 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(LINEAR);

4.2 PREV(前值填充)

适用于状态类数据,如开关状态、设备模式等。

-- 前值填充示例
SELECT ts,INTERP(设备状态) AS 当前状态
FROM device_status 
RANGE('2024-01-01 08:00:00', '2024-01-01 18:00:00') 
EVERY(10m) 
FILL(PREV);

4.3 NEXT(后值填充)

适用于预测性数据填充。

-- 后值填充示例
SELECT ts,INTERP(预测功率) AS 预测值
FROM power_forecast 
RANGE('2024-01-01 12:00:00', '2024-01-01 13:00:00') 
EVERY(15m) 
FILL(NEXT);

4.4 VALUE(指定值填充)

适用于有默认值的场景。

-- 指定值填充示例
SELECT ts,INTERP(报警级别) AS 报警级别
FROM alarm_log 
RANGE('2024-01-01 00:00:00', '2024-01-01 23:59:59') 
EVERY(1h) 
FILL(VALUE, 0);

4.5 NEAR(最近值填充)

适用于需要使用距离当前时间点最近的数据进行插值的场景(v3.3.4.9+)。

-- 最近值填充示例
SELECT ts,INTERP(电压) AS 电压值
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(NEAR);-- 时间范围扩展示例
-- 在指定时间点前后10秒范围内查找数据进行插值
SELECT ts,INTERP(电压) AS 电压值
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:30:00', 10s) 
FILL(PREV, 220);

4.6 ignore_null_values 参数使用

控制是否忽略 NULL 值的参数,对数据插值结果有重要影响。

-- 不忽略NULL值(默认行为)
SELECT ts,INTERP(电压, 0) AS 电压值
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(LINEAR);-- 忽略NULL值
SELECT ts,INTERP(电压, 1) AS 电压值
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(LINEAR);-- 对比NULL值处理的差异
SELECT ts,INTERP(电压, 0) AS 包含NULL,INTERP(电压, 1) AS 忽略NULL
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(LINEAR);

5. 高级特性与应用

5.1 伪列的使用

TDengine 提供了多个伪列来增强 INTERP 函数的功能。

-- 使用_isfilled判断数据是否为插值结果
SELECT ts,INTERP(电压) AS 电压值,_isfilled AS 是否插值,CASE WHEN _isfilled = 1 THEN '插值数据'ELSE '原始数据'END AS 数据类型
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(LINEAR);-- 使用_irowts获取插值时间戳
SELECT ts,INTERP(电压) AS 电压值,_irowts AS 插值时间戳,_isfilled AS 是否插值
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(LINEAR);-- 使用_irowts_origin获取原始数据时间戳(仅PREV/NEXT/NEAR模式)
SELECT ts,INTERP(电压) AS 电压值,_irowts_origin AS 原始数据时间戳,_isfilled AS 是否插值
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(PREV);

5.2 超级表的处理

-- 超级表插值(所有子表数据按主键排序)
SELECT ts,INTERP(电压) AS 电压值,tbname
FROM tdasset.meters 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(LINEAR);-- 使用PARTITION BY tbname强制规约到单个时间线
SELECT ts,INTERP(电压) AS 电压值,tbname
FROM tdasset.meters 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(LINEAR)
PARTITION BY tbname;

5.3 时间范围扩展功能

-- 时间范围扩展:在指定时间点前后查找数据
-- 在2024-01-01 10:30:00前后10秒范围内查找数据
SELECT ts,INTERP(电压) AS 电压值
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:30:00', 10s) 
FILL(PREV, 220);-- 使用NEXT模式在时间点后查找数据
SELECT ts,INTERP(电压) AS 电压值
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:30:00', 30s) 
FILL(NEXT, 220);-- 使用NEAR模式在时间点前后查找最近数据
SELECT ts,INTERP(电压) AS 电压值
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:30:00', 15s) 
FILL(NEAR, 220);

6. 在流计算中的应用

6.1 流计算中的 INTERP 使用

在流计算中,INTERP 不支持使用 RANGE,但需要与 EVERY 和 FILL 关键字一起使用。

-- 流计算中使用 INTERP 进行数据补齐
CREATE STREAM IF NOT EXISTS voltage_interp_stream
INTERVAL(1m)
FROM tdasset.vt_em-6
INTO voltage_interp_result
AS SELECT _twstart AS ts,INTERP(电压) AS 平均电压
FROM tdasset.vt_em-6
WHERE ts >= _twstart AND ts <= _twend
EVERY(10s)
FILL(LINEAR);-- 流计算中忽略NULL值的插值
CREATE STREAM IF NOT EXISTS current_interp_stream
INTERVAL(1m)
FROM tdasset.vt_em-6
INTO current_interp_result
AS SELECT _twstart AS ts,INTERP(电流, 1) AS 电流值
FROM tdasset.vt_em-6
WHERE ts >= _twstart AND ts <= _twend
EVERY(30s)
FILL(PREV);

6.2 告警场景应用

-- 基于插值数据的告警流
CREATE STREAM IF NOT EXISTS voltage_alarm_stream
INTERVAL(1m)
FROM tdasset.vt_em-6
INTO voltage_alarm_result
AS SELECT _twstart AS ts,CASE WHEN INTERP(电压, 1) > 250 THEN '高压告警'WHEN INTERP(电压, 1) < 200 THEN '低压告警'ELSE '正常'END AS 告警状态,INTERP(电压, 1) AS 电压值
FROM tdasset.vt_em-6
WHERE ts >= _twstart AND ts <= _twend
EVERY(30s)
FILL(LINEAR);-- 基于插值数据的功率监控流
CREATE STREAM IF NOT EXISTS power_monitor_stream
INTERVAL(5m)
FROM tdasset.vt_em-6
INTO power_monitor_result
AS SELECT _twstart AS ts,INTERP(功率, 1) AS 当前功率,CASE WHEN INTERP(功率, 1) > 5000 THEN '功率过高'WHEN INTERP(功率, 1) < 100 THEN '功率异常'ELSE '正常'END AS 功率状态
FROM tdasset.vt_em-6
WHERE ts >= _twstart AND ts <= _twend
EVERY(1m)
FILL(PREV);

7. 性能优化建议

7.1 时间范围优化

-- 避免过大的时间范围
-- 推荐:限制在合理的时间范围内
SELECT ts, INTERP(电压) 
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(LINEAR);-- 不推荐:时间范围过大
-- SELECT ts, INTERP(电压) 
-- FROM tdasset.vt_em-6 
-- RANGE('2024-01-01 00:00:00', '2024-12-31 23:59:59') 
-- EVERY(1s) 
-- FILL(LINEAR);

7.2 插值间隔优化

-- 根据数据特点选择合适的插值间隔
-- 对于电压数据,1分钟间隔通常足够
SELECT ts, INTERP(电压) 
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(LINEAR);

7.3 ignore_null_values 参数优化

-- 当数据中包含较多NULL值时,使用ignore_null_values=1可以提高插值效果
SELECT ts, INTERP(电压, 1) 
FROM tdasset.vt_em-6 
RANGE('2024-01-01 10:00:00', '2024-01-01 11:00:00') 
EVERY(1m) 
FILL(LINEAR);

8. 注意事项

8.1 数据类型限制

  • INTERP 函数主要适用于数值类型数据
  • 对于字符串类型,建议使用 PREV 或 NEXT 填充模式

8.2 NULL 值处理

  • 当选择 FILL(NULL) 时,缺失的数据点会返回 NULL
  • 使用 ignore_null_values=1 可以在插值计算中忽略 NULL 值
  • 在进行后续计算时需要考虑 NULL 值的影响

8.3 性能考虑

  • 插值计算会消耗额外的计算资源
  • 在大数据量场景下,建议合理设置时间范围和插值间隔
  • 使用伪列会增加额外的计算开销

8.4 语法限制

  • INTERP 函数不能与其他函数一起查询
  • 不能与窗口子句、分组子句同时使用
  • 在流计算中不支持 RANGE 子句

8.5 版本兼容性

  • _irowts 伪列需要 v3.0.2.0 及以上版本
  • _isfilled 伪列需要 v3.0.3.0 及以上版本
  • NEAR 填充模式和时间范围扩展需要 v3.3.4.9 及以上版本
  • _irowts_origin 伪列需要 v3.3.4.9 及以上版本

9. 常见问题解答

Q1: INTERP 函数与 FILL 子句的区别?

A1: INTERP 函数专门用于在指定时间点进行插值,而 FILL 子句主要用于在聚合查询中填充空值。INTERP 提供了更精确的时间点插值控制和更多的填充选项。

Q2: 如何选择合适的填充模式?

A2:

  • 连续变化的数据(如温度、电压):使用 LINEAR
  • 状态类数据(如开关状态):使用 PREV
  • 需要最近数据的场景:使用 NEAR
  • 有明确默认值的场景:使用 VALUE

Q3: ignore_null_values 参数什么时候使用?

A3: 当数据中包含较多 NULL 值,并且希望在插值计算中忽略这些 NULL 值时使用。设置为 1 可以提高插值的连续性和准确性。

Q4: INTERP 函数对性能的影响?

A4: INTERP 函数会增加计算负担,特别是在大时间范围和高频插值的情况下。建议根据实际需求合理设置参数,避免过度密集的插值计算。

Q5: 能否在子查询中使用 INTERP?

A5: 可以,但需要注意子查询的时间范围设置,确保能够获取到足够的数据进行插值计算。

Q6: 时间范围扩展功能如何使用?

A6: 使用 RANGE(‘时间点’, 时间范围) 的格式,如 RANGE(‘2024-01-01 10:00:00’, 10s) 表示在指定时间点前后 10 秒范围内查找数据。此功能仅支持 PREV/NEXT/NEAR 填充模式。

Q7: 伪列的作用是什么?

A7:

  • _isfilled: 判断返回的数据是原始数据还是插值数据
  • _irowts: 获取插值点对应的时间戳
  • _irowts_origin: 获取插值时使用的原始数据时间戳(仅限PREV/NEXT/NEAR模式)

10. 实践建议

  1. 合理设置时间范围:避免过大的时间跨度,影响查询性能
  2. 选择合适的插值间隔:根据数据特点和业务需求选择
  3. 正确使用 ignore_null_values:在数据包含大量 NULL 值时启用
  4. 选择正确的填充模式:根据数据类型和业务语义选择
  5. 合理使用伪列:在需要了解插值详情时使用,但要注意性能开销
  6. 结合索引优化:确保时间列有适当的索引
  7. 监控查询性能:在生产环境中监控 INTERP 查询的性能表现
  8. 版本管理:注意不同版本的功能差异,选择合适的版本使用相应功能

通过合理使用 INTERP 函数及其高级特性,可以有效解决时间序列数据中的插值问题,提高数据分析的准确性和完整性。

关于 TDengine

TDengine 是一款专为物联网、工业互联网等场景设计并优化的大数据平台,其核心模块是高性能、集群开源、云原生、极简的时序数据库。它能安全高效地将大量设备每天产生的高达 TB 甚至 PB 级的数据进行汇聚、存储、分析和分发,并提供 AI 智能体对数据进行预测与异常检测,提供实时的商业洞察。

http://www.dtcms.com/a/282354.html

相关文章:

  • 医疗AI“全栈原生态“系统设计路径分析
  • 多人协作游戏中,团队共同获取的装备如何确定按份共有或共同共有
  • 二代身份证识别技术的发展:从机器学习到深度学习
  • 【机器学习】数据理解:数据导入、数据审查与数据可视化
  • Qt小组件 - 7 SQL Thread Qt访问数据库ORM
  • gin go-kratos go-zero框架对比
  • 【后端】配置SqlSugar ORM框架并添加仓储
  • 【论文阅读 | IF 2025 | COMO:用于多模态目标检测的跨 Mamba 交互与偏移引导融合】
  • Web3.0与元宇宙:重构数字文明的技术范式与社会变革
  • 以太网供电与自愈网络对音视频系统的益处
  • 基于 elements3 包装的 可展开 table 组件
  • Elasticsearch+Logstash+Filebeat+Kibana部署
  • 前端状态管理对比:Redux与Vuex的深度分析
  • 利用 Spring 的 `@Scheduled` 注解结合简单的状态跟踪实现空闲检测方案
  • Node.js Domain 模块深度解析与最佳实践
  • 玩转Docker | 使用Docker部署vnStat网络流量监控服务
  • WPF 导入自定义字体并实现按钮悬停高亮效果
  • 微软AutoGen:多智能体协作的工业级解决方案
  • PostGres超过最大连接数报错
  • Linux LVS集群技术详解与实战指南
  • 通信算法之292:大疆DJI云哨系统-DroneID物理层协议解析-O1/O2/O3/O4机型都可以CRC正确
  • Redisson
  • 【知识图谱】Neo4j桌面版运行不起来怎么办?Neo4j Desktop无法打开!
  • C++设计模式之创建型模式
  • Qt小组件 - 6 异步运行函数
  • 暑假---作业2
  • QT技巧之快速搭建串口收发平台
  • Qt中实现文件(文本文件)内容对比
  • Django基础(三)———模板
  • Python设计模式深度解析:装饰器模式(Decorator Pattern)完全指南