TDengine 时序函数 STATECOUNT 用户手册
STATECOUNT 函数用户手册(智能电表场景)
1. 函数概述
STATECOUNT
是 TDengine 的时序状态函数,用于统计满足某个条件的连续记录的个数。该函数在智能电表监控系统中特别适用于检测连续的异常状态,如连续的高电压、持续的过载等状况。
STATECOUNT 函数概述表格
项目 | 详细说明 |
---|---|
函数名称 | STATECOUNT |
功能说明 | 返回满足某个条件的连续记录的个数,结果作为新的一列追加在每行后面。条件根据参数计算,如果条件为 true 则加 1,条件为 false 则重置为 -1,如果数据为 NULL,跳过该条数据。 |
语法格式 | STATECOUNT(expr, oper, val) |
参数说明 | expr: 数值列表达式 oper: 比较操作符 val: 比较数值 |
操作符范围 (oper) | “LT” (小于) “GT” (大于) “LE” (小于等于) “GE” (大于等于) “NE” (不等于) “EQ” (等于) 注:不区分大小写,需用引号包围 |
数值范围 (val) | 数值型 |
返回结果类型 | INTEGER |
适用数据类型 | 数值类型 (TINYINT, SMALLINT, INT, BIGINT, FLOAT, DOUBLE) |
计数规则 | 条件为 true:计数 +1 条件为 false:重置为 -1 数据为 NULL:跳过该条数据 |
嵌套子查询支持 | 支持应用在子查询上 |
适用于 | 表和超级表 |
超级表使用要求 | 必须使用 PARTITION BY,不支持 GROUP BY |
SELECT 语句限制 | 每个 SELECT 语句只能包含一个 STATECOUNT 函数 |
WHERE 子句限制 | 不能直接在 WHERE 子句中使用,需通过嵌套查询实现 |
使用限制 | 不能和窗口操作一起使用 例如:INTERVAL / STATE_WINDOW / SESSION_WINDOW |
应用场景 | 连续异常状态检测 设备故障监控 质量控制分析 趋势变化识别 |
使用示例对照表
场景 | 正确用法 ✅ | 错误用法 ❌ |
---|---|---|
基本使用 | SELECT STATECOUNT(voltage, "GE", 240) FROM d1; | SELECT STATECOUNT(voltage, GE, 240) FROM d1; |
多函数限制 | SELECT ts, voltage, STATECOUNT(voltage, "GE", 240) FROM d1; | SELECT STATECOUNT(voltage, "GE", 240), STATECOUNT(current, "GT", 20) FROM d1; |
WHERE 过滤 | SELECT * FROM (SELECT ts, STATECOUNT(voltage, "GE", 240) AS cnt FROM d1) WHERE cnt >= 5; | SELECT ts FROM d1 WHERE STATECOUNT(voltage, "GE", 240) >= 5; |
超级表使用 | SELECT STATECOUNT(voltage, "GE", 240) FROM meters PARTITION BY tbname; | SELECT STATECOUNT(voltage, "GE", 240) FROM meters GROUP BY tbname; |
窗口函数 | SELECT ts, STATECOUNT(voltage, "GE", 240) FROM d1; | SELECT STATECOUNT(voltage, "GE", 240) FROM d1 INTERVAL(1h); |
2. 语法
STATECOUNT(expr, oper, val)
参数说明
- expr:需要进行状态检测的数值列
- oper:比较操作符,支持以下操作:
"LT"
:小于"GT"
:大于"LE"
:小于等于"GE"
:大于等于"NE"
:不等于"EQ"
:等于
- val:比较的数值
返回值说明
- 返回类型:INTEGER
- 计数规则:
- 条件为 true:计数 +1
- 条件为 false:重置为 -1
- 数据为 NULL:跳过该条数据
3. 计算过程与返回值说明
3.1 计算过程
假设有如下智能电表电压数据:
时间戳 | 电压值 (V) |
---|---|
10:00:00 | 220.0 |
10:01:00 | 245.0 |
10:02:00 | 248.0 |
10:03:00 | 235.0 |
10:04:00 | 218.0 |
10:05:00 | 250.0 |
10:06:00 | 252.0 |
计算 STATECOUNT(voltage, “GE”, 240)
计算过程:
- 第1行:220.0 < 240,条件为 false,返回 -1
- 第2行:245.0 >= 240,条件为 true,开始计数,返回 1
- 第3行:248.0 >= 240,条件为 true,继续计数,返回 2
- 第4行:235.0 < 240,条件为 false,重置计数,返回 -1
- 第5行:218.0 < 240,条件为 false,保持重置状态,返回 -1
- 第6行:250.0 >= 240,条件为 true,重新开始计数,返回 1
- 第7行:252.0 >= 240,条件为 true,继续计数,返回 2
3.2 返回值样式
SELECT ts, voltage, STATECOUNT(voltage, "GE", 240) AS high_voltage_count
FROM d1
ORDER BY ts;
结果示例:
ts | voltage | high_voltage_count |
---|---|---|
10:00:00 | 220.0 | -1 |
10:01:00 | 245.0 | 1 |
10:02:00 | 248.0 | 2 |
10:03:00 | 235.0 | -1 |
10:04:00 | 218.0 | -1 |
10:05:00 | 250.0 | 1 |
10:06:00 | 252.0 | 2 |
3.3 NULL 值处理示例
假设数据中包含 NULL 值:
时间戳 | 电压值 (V) |
---|---|
10:00:00 | 245.0 |
10:01:00 | NULL |
10:02:00 | 248.0 |
10:03:00 | 235.0 |
计算 STATECOUNT(voltage, “GE”, 240)
处理过程:
- 第1行:245.0 >= 240,条件为 true,返回 1
- 第2行:NULL,跳过该条数据,不输出结果
- 第3行:248.0 >= 240,条件为 true,继续计数,返回 2
- 第4行:235.0 < 240,条件为 false,重置计数,返回 -1
结果示例:
ts | voltage | high_voltage_count |
---|---|---|
10:00:00 | 245.0 | 1 |
10:02:00 | 248.0 | 2 |
10:03:00 | 235.0 | -1 |
3.4 不同操作符的计算示例
示例数据
时间戳 | 电流值 (A) |
---|---|
10:00:00 | 15.0 |
10:01:00 | 25.0 |
10:02:00 | 20.0 |
10:03:00 | 25.0 |
使用 “GT” 操作符:STATECOUNT(current, “GT”, 20)
计算结果:
ts | current | STATECOUNT(current, “GT”, 20) |
---|---|---|
10:00:00 | 15.0 | -1 |
10:01:00 | 25.0 | 1 |
10:02:00 | 20.0 | -1 |
10:03:00 | 25.0 | 1 |
使用 “EQ” 操作符:STATECOUNT(current, “EQ”, 25)
计算结果:
ts | current | STATECOUNT(current, “EQ”, 25) |
---|---|---|
10:00:00 | 15.0 | -1 |
10:01:00 | 25.0 | 1 |
10:02:00 | 20.0 | -1 |
10:03:00 | 25.0 | 1 |
4. 智能电表应用场景
基于智能电表数据库结构:
-- 超级表
CREATE STABLE meters (ts TIMESTAMP,voltage FLOAT,current FLOAT,power FLOAT
) TAGS (device_id VARCHAR(50),location VARCHAR(50)
);-- 子表
CREATE TABLE d1 USING meters TAGS ('meter001', 'California.SanFrancisco');
4.1 电压异常监控
-- 监控连续高电压状况(电压 >= 240V)
SELECT ts,voltage,STATECOUNT(voltage, "GE", 240) AS high_voltage_count
FROM d1
ORDER BY ts;-- 检测连续低电压状况(电压 <= 200V)
SELECT ts,voltage,STATECOUNT(voltage, "LE", 200) AS low_voltage_count
FROM d1
WHERE ts >= NOW() - 1h
ORDER BY ts;-- 监控电压不稳定(电压不等于额定值220V)
SELECT ts,voltage,STATECOUNT(voltage, "NE", 220) AS voltage_unstable_count
FROM d1
WHERE ts >= NOW() - 30m
ORDER BY ts;
4.2 电流过载检测
-- 检测连续过载状况(电流 > 20A)
SELECT ts,current,STATECOUNT(current, "GT", 20) AS overload_count
FROM d1
ORDER BY ts;-- 监控连续轻载状况(电流 < 5A)
SELECT ts,current,STATECOUNT(current, "LT", 5) AS light_load_count
FROM d1
WHERE ts >= NOW() - 2h
ORDER BY ts;-- 检测电流异常(电流 = 0,可能是断线)
SELECT ts,current,STATECOUNT(current, "EQ", 0) AS zero_current_count
FROM d1
ORDER BY ts;
4.3 功率消耗分析
-- 监控连续高功耗(功率 >= 5000W)
SELECT ts,power,STATECOUNT(power, "GE", 5000) AS high_power_count
FROM d1
ORDER BY ts;-- 检测设备空闲状态(功率 <= 100W)
SELECT ts,power, STATECOUNT(power, "LE", 100) AS idle_count
FROM d1
WHERE ts >= NOW() - 4h
ORDER BY ts;
4.4 超级表状态监控(使用 PARTITION BY)
-- 按子表分区监控所有设备的电压状态
SELECT ts,tbname,voltage,STATECOUNT(voltage, "GE", 240) AS high_voltage_count
FROM meters
WHERE ts >= NOW() - 30m
PARTITION BY tbname
ORDER BY tbname, ts;
4.5 状态持续时间分析
❌ 错误写法(包含两个 STATECOUNT):
-- 这会导致错误,因为包含了两个 STATECOUNT 函数
SELECT ts,voltage,STATECOUNT(voltage, "GE", 240) AS consecutive_high,CASE WHEN STATECOUNT(voltage, "GE", 240) > 10 THEN '长期高压'WHEN STATECOUNT(voltage, "GE", 240) > 5 THEN '短期高压'WHEN STATECOUNT(voltage, "GE", 240) = -1 THEN '正常'ELSE '其他'END AS voltage_status
FROM d1
WHERE ts >= NOW() - 1h
ORDER BY ts;
✅ 正确写法(使用嵌套查询):
-- 结合时间戳分析状态持续情况
SELECT ts,voltage,consecutive_high,CASE WHEN consecutive_high > 10 THEN '长期高压'WHEN consecutive_high > 5 THEN '短期高压'WHEN consecutive_high = -1 THEN '正常'ELSE '其他'END AS voltage_status
FROM (SELECT ts,voltage,STATECOUNT(voltage, "GE", 240) AS consecutive_highFROM d1WHERE ts >= NOW() - 1hORDER BY ts
)
ORDER BY ts;
5. 实际应用案例
5.1 多设备对比分析
-- 使用超级表按设备对比电压状态
SELECT tbname,device_id,ts,voltage,STATECOUNT(voltage, "GE", 240) AS high_voltage_count
FROM meters
WHERE ts >= NOW() - 1h
PARTITION BY tbname
ORDER BY tbname, ts;
5.2 区域电力质量监控
-- 按子表监控电力质量状态
SELECT tbname,ts,voltage,STATECOUNT(voltage, "NE", 220) AS voltage_unstable_count
FROM meters
WHERE ts >= NOW() - 2h
PARTITION BY tbname
ORDER BY tbname, ts;
5.3 设备状态变化趋势
❌ 错误写法:
-- 这会导致错误,因为包含了多个 STATECOUNT 函数
SELECT ts,voltage,current,STATECOUNT(voltage, "GE", 240) AS voltage_high_count,STATECOUNT(current, "GT", 20) AS current_high_count,CASE WHEN STATECOUNT(voltage, "GE", 240) > 0 AND STATECOUNT(current, "GT", 20) > 0 THEN '电压电流双高'WHEN STATECOUNT(voltage, "GE", 240) > 0 THEN '仅电压高'WHEN STATECOUNT(current, "GT", 20) > 0 THEN '仅电流高'ELSE '正常'END AS device_status
FROM d1
WHERE ts >= NOW() - 1h
ORDER BY ts;
✅ 正确写法(分别查询):
-- 分析设备电压状态变化趋势
SELECT ts,voltage,voltage_high_count,CASE WHEN voltage_high_count > 0 THEN '电压异常'ELSE '电压正常'END AS voltage_status
FROM (SELECT ts,voltage,STATECOUNT(voltage, "GE", 240) AS voltage_high_countFROM d1WHERE ts >= NOW() - 1hORDER BY ts
)
ORDER BY ts;-- 分析设备电流状态变化趋势
SELECT ts,current,current_high_count,CASE WHEN current_high_count > 0 THEN '电流异常'ELSE '电流正常'END AS current_status
FROM (SELECT ts,current,STATECOUNT(current, "GT", 20) AS current_high_countFROM d1WHERE ts >= NOW() - 1hORDER BY ts
)
ORDER BY ts;
6. 高级应用技巧
6.1 阈值动态调整
-- 使用不同阈值分别检测
-- 轻度高电压检测
SELECT ts,voltage,STATECOUNT(voltage, "GE", 230) AS mild_high_voltage
FROM d1
WHERE ts >= NOW() - 1h
ORDER BY ts;-- 严重高电压检测
SELECT ts,voltage,STATECOUNT(voltage, "GE", 250) AS severe_high_voltage
FROM d1
WHERE ts >= NOW() - 1h
ORDER BY ts;
6.2 时间窗口内状态统计
-- 在特定时间段内分析状态变化
SELECT ts,voltage,STATECOUNT(voltage, "LT", 210) AS low_voltage_count
FROM d1
WHERE ts BETWEEN '2024-01-01 08:00:00' AND '2024-01-01 18:00:00'
ORDER BY ts;
7. 使用限制
7.1 函数分类说明
STATECOUNT 属于时序状态函数,有以下使用限制:
-- ✅ 正确:单独使用
SELECT STATECOUNT(voltage, "GE", 240) FROM d1;-- ✅ 正确:与普通列、选择函数一起使用
SELECT ts, voltage, STATECOUNT(voltage, "GE", 240) FROM d1;-- ❌ 错误:不能与窗口操作一起使用
SELECT STATECOUNT(voltage, "GE", 240) FROM d1 INTERVAL(1h);
SELECT STATECOUNT(voltage, "GE", 240) FROM d1 STATE_WINDOW(voltage);
SELECT STATECOUNT(voltage, "GE", 240) FROM d1 SESSION(ts, 10s);-- ❌ 错误:不支持子查询
SELECT STATECOUNT(voltage, "GE", 240) FROM (SELECT * FROM d1);
7.2 单个 STATECOUNT 函数限制
由于 STATECOUNT 函数会跳过 NULL 值,可能导致不同列的输出行数不同,因此 SELECT 语句中只能包含一个 STATECOUNT 函数:
-- ❌ 错误:不能在同一个 SELECT 中使用多个 STATECOUNT
SELECT ts,voltage,current,STATECOUNT(voltage, "GE", 240) AS high_voltage_count,STATECOUNT(current, "GT", 20) AS overload_count
FROM d1;-- ❌ 错误:多个 STATECOUNT 会导致行数不匹配
SELECT STATECOUNT(voltage, "GE", 240) AS high_voltage_count,STATECOUNT(current, "GT", 20) AS overload_count
FROM d1;-- ❌ 错误:即使在 CASE 中重复使用同一个 STATECOUNT 也不行
SELECT ts,voltage,STATECOUNT(voltage, "GE", 240) AS voltage_high_count,CASE WHEN STATECOUNT(voltage, "GE", 240) > 0 THEN '电压异常'ELSE '电压正常'END AS device_status
FROM d1;-- ✅ 正确:每次只使用一个 STATECOUNT
SELECT ts,voltage,STATECOUNT(voltage, "GE", 240) AS high_voltage_count
FROM d1;-- ✅ 正确:使用嵌套查询避免重复调用 STATECOUNT
SELECT ts,voltage,voltage_high_count,CASE WHEN voltage_high_count > 0 THEN '电压异常'ELSE '电压正常'END AS device_status
FROM (SELECT ts,voltage,STATECOUNT(voltage, "GE", 240) AS voltage_high_countFROM d1ORDER BY ts
);
7.3 WHERE 子句使用限制
STATECOUNT 函数不能直接在 WHERE 子句中使用,需要通过嵌套查询实现:
-- ❌ 错误:不能在 WHERE 子句中直接使用
SELECT ts, voltage
FROM d1
WHERE STATECOUNT(voltage, "GE", 240) >= 5;-- ✅ 正确:使用嵌套查询实现过滤
SELECT ts, voltage, high_voltage_count
FROM (SELECT ts, voltage, STATECOUNT(voltage, "GE", 240) AS high_voltage_countFROM d1ORDER BY ts
)
WHERE high_voltage_count >= 5;
7.4 超级表使用限制
STATECOUNT 在超级表上有特殊的使用要求:
-- ❌ 错误:不能在超级表上直接使用
SELECT STATECOUNT(voltage, "GE", 240) FROM meters;-- ❌ 错误:不能使用 GROUP BY tbname
SELECT tbname, STATECOUNT(voltage, "GE", 240) FROM meters GROUP BY tbname;-- ✅ 正确:必须使用 PARTITION BY tbname
SELECT tbname, STATECOUNT(voltage, "GE", 240) FROM meters PARTITION BY tbname;-- ✅ 正确:可以按tbname分区
SELECT tbname, STATECOUNT(voltage, "GE", 240) FROM meters PARTITION BY tbname;
7.5 数据类型要求
-- ✅ 支持的数据类型
SELECT STATECOUNT(voltage, "GE", 240) FROM d1; -- FLOAT
SELECT STATECOUNT(current, "GT", 10) FROM d1; -- FLOAT
SELECT STATECOUNT(power, "LE", 5000) FROM d1; -- FLOAT-- ❌ 不支持的数据类型
SELECT STATECOUNT(device_id, "EQ", 1) FROM meters; -- 字符串类型
SELECT STATECOUNT(ts, "GT", 100) FROM d1; -- 时间戳类型
7.6 操作符格式要求
-- ✅ 正确的操作符格式(不区分大小写,但需要引号包围)
SELECT STATECOUNT(voltage, "GE", 240) FROM d1;
SELECT STATECOUNT(voltage, "ge", 240) FROM d1;
SELECT STATECOUNT(voltage, "Ge", 240) FROM d1;-- ❌ 错误的操作符格式
SELECT STATECOUNT(voltage, GE, 240) FROM d1; -- 缺少引号
SELECT STATECOUNT(voltage, >=, 240) FROM d1; -- 使用符号而非文字
8. 多指标监控的解决方案
8.1 分步查询方案
由于不能在同一个 SELECT 中使用多个 STATECOUNT,需要分步查询:
-- 步骤1:查询电压状态
SELECT ts,voltage,STATECOUNT(voltage, "GE", 240) AS high_voltage_count
FROM d1
WHERE ts >= NOW() - 1h
ORDER BY ts;-- 步骤2:查询电流状态
SELECT ts,current,STATECOUNT(current, "GT", 20) AS overload_count
FROM d1
WHERE ts >= NOW() - 1h
ORDER BY ts;-- 步骤3:查询功率状态
SELECT ts,power,STATECOUNT(power, "EQ", 0) AS zero_power_count
FROM d1
WHERE ts >= NOW() - 1h
ORDER BY ts;
8.2 应用层数据合并
-- 在应用层将多个查询结果合并分析
-- 应用程序伪代码示例:
/*
voltage_states = query("SELECT ts, voltage, STATECOUNT(voltage, 'GE', 240) FROM d1");
current_states = query("SELECT ts, current, STATECOUNT(current, 'GT', 20) FROM d1");
power_states = query("SELECT ts, power, STATECOUNT(power, 'EQ', 0) FROM d1");// 按时间戳合并数据
combined_analysis = merge_by_timestamp(voltage_states, current_states, power_states);
*/
9. 嵌套查询应用示例
9.1 过滤连续异常状态
-- 查找连续5次以上高电压的记录
SELECT ts, voltage, high_voltage_count
FROM (SELECT ts, voltage, STATECOUNT(voltage, "GE", 240) AS high_voltage_countFROM d1WHERE ts >= NOW() - 2hORDER BY ts
)
WHERE high_voltage_count >= 5;-- 查找连续3次以上过载的记录
SELECT ts, current, overload_count
FROM (SELECT ts, current, STATECOUNT(current, "GT", 20) AS overload_countFROM d1WHERE ts >= NOW() - 1hORDER BY ts
)
WHERE overload_count >= 3;
9.2 超级表嵌套查询
-- 超级表中查找各设备的连续异常状态
SELECT tbname, device_id, ts, voltage, high_voltage_count
FROM (SELECT tbname,device_id,ts, voltage, STATECOUNT(voltage, "GE", 240) AS high_voltage_countFROM metersWHERE ts >= NOW() - 1hPARTITION BY tbnameORDER BY tbname, ts
)
WHERE high_voltage_count >= 5;
9.3 状态变化点检测
-- 检测异常开始点
SELECT ts, voltage, high_voltage_count
FROM (SELECT ts, voltage, STATECOUNT(voltage, "GE", 240) AS high_voltage_countFROM d1WHERE ts >= NOW() - 2hORDER BY ts
)
WHERE high_voltage_count = 1;-- 检测长期异常状态
SELECT ts, voltage, high_voltage_count
FROM (SELECT ts, voltage, STATECOUNT(voltage, "GE", 240) AS high_voltage_countFROM d1WHERE ts >= NOW() - 2hORDER BY ts
)
WHERE high_voltage_count >= 10;
9.4 统计分析应用
-- 统计各设备的异常频次
SELECT tbname,device_id,COUNT(*) AS abnormal_periods
FROM (SELECT tbname,device_id,ts,STATECOUNT(voltage, "GE", 240) AS high_voltage_countFROM metersWHERE ts >= NOW() - 24hPARTITION BY tbnameORDER BY tbname, ts
)
WHERE high_voltage_count = 1 -- 只统计异常开始的次数
GROUP BY tbname, device_id
ORDER BY abnormal_periods DESC;
10. 实际应用案例进阶
10.1 报警系统实现
-- 实现多级报警系统
SELECT ts,voltage,CASE WHEN high_voltage_count >= 10 THEN '严重报警'WHEN high_voltage_count >= 5 THEN '一般报警'WHEN high_voltage_count >= 3 THEN '预警'ELSE '正常'END AS alarm_level
FROM (SELECT ts,voltage,STATECOUNT(voltage, "GE", 240) AS high_voltage_countFROM d1WHERE ts >= NOW() - 30mORDER BY ts
)
WHERE high_voltage_count >= 3;
10.2 设备健康度评估
-- 基于电压状态评估设备健康度
SELECT tbname,device_id,ts,voltage,CASE WHEN high_voltage_count >= 20 THEN '设备异常'WHEN high_voltage_count >= 10 THEN '设备预警'WHEN high_voltage_count > 0 THEN '设备关注'ELSE '设备正常'END AS device_health
FROM (SELECT tbname,device_id,ts,voltage,STATECOUNT(voltage, "GE", 240) AS high_voltage_countFROM metersWHERE ts >= NOW() - 1hPARTITION BY tbnameORDER BY tbname, ts
)
WHERE high_voltage_count > 0;
关于 TDengine
TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。