TDengine 字符串函数 CONCAT_WS 用户手册

CONCAT_WS 函数
功能说明
CONCAT_WS 函数用于将多个字符串使用指定的分隔符连接成一个字符串。函数名称中的 “WS” 代表 “With Separator”(带分隔符)。
语法
CONCAT_WS(separator, string1, string2, ...)
参数说明
- separator: 分隔符,用于连接各个字符串,可以是
VARCHAR或NCHAR类型 - string1, string2, …: 待连接的字符串,可以是
VARCHAR或NCHAR类型 - 参数数量:最少 3 个参数(1 个分隔符 + 2 个待连接字符串),最多 9 个参数(1 个分隔符 + 8 个待连接字符串)
返回值类型
- 如果任意一个参数为
NCHAR类型,则返回NCHAR类型 - 否则返回
VARCHAR类型 - 返回字符串的最大长度受限于系统最大字段长度
嵌套子查询支持
适用于内层查询和外层查询。
适用于
表和超级表。
使用规则
- 分隔符位置: 第一个参数必须是分隔符
- 类型提升: 如果参数中包含
NCHAR类型,结果会自动提升为NCHAR类型 - 字符集转换:
VARCHAR和NCHAR混用时,VARCHAR会被转换为NCHAR,字节数会相应增加 - NULL 值处理:
- 如果分隔符为 NULL,结果为 NULL
- 其他参数为 NULL 时会被跳过(不参与连接)
- 使用限制: 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用
智能电表应用示例
场景 1: 生成设备标识字符串
目的: 为每个智能电表创建唯一的、易读的设备标识,方便运维人员识别和管理
-- 智能电表表结构
CREATE STABLE meters (ts TIMESTAMP,current FLOAT,voltage INT,phase FLOAT,power DOUBLE,device_id VARCHAR(64),region VARCHAR(32),status_msg VARCHAR(128)
) TAGS (groupid INT,location VARCHAR(64)
);-- 生成完整的设备位置标识
SELECT CONCAT_WS('-', region, location, device_id) AS full_device_id,LAST(ts) AS last_update,AVG(power) AS avg_power
FROM meters
WHERE ts >= NOW - 1h
GROUP BY groupid, region, location, device_id
ORDER BY avg_power DESC;
结果示例:
full_device_id | last_update | avg_power
-------------------------------------------------------------------------
华东-上海办公楼10层1001室-M10001 | 2025-11-07 14:30:00 | 2.35
华东-上海办公楼10层1002室-M10002 | 2025-11-07 14:30:00 | 1.89
华北-北京数据中心3层机房A-M20015 | 2025-11-07 14:30:00 | 15.67
场景 2: 生成告警信息描述
目的: 将多个字段组合成可读的告警描述,便于告警通知和日志记录
-- 生成电压异常告警信息
SELECT ts,device_id,CONCAT_WS(' | ', CASE WHEN voltage > 240 THEN '告警:电压过高'WHEN voltage < 210 THEN '告警:电压过低'ELSE '正常'END,region,location,CONCAT('当前电压:', CAST(voltage AS VARCHAR(10)), 'V'),status_msg) AS alert_message
FROM meters
WHERE ts >= NOW - 1dAND (voltage > 240 OR voltage < 210)
ORDER BY ts DESC
LIMIT 20;
结果示例:
ts | device_id | alert_message
------------------------------------------------------------------------------------
2025-11-07 14:25:00 | M10001 | 告警:电压过高 | 华东 | 上海办公楼10层1001室 | 当前电压:245V | 设备运行异常
2025-11-07 14:15:00 | M10032 | 告警:电压过低 | 华东 | 上海办公楼8层801室 | 当前电压:205V | 负载过大
2025-11-07 14:10:00 | M20015 | 告警:电压过高 | 华北 | 北京数据中心3层机房A | 当前电压:242V | 正常运行
场景 3: 生成CSV格式的数据导出
目的: 将电表数据导出为CSV格式,方便与第三方系统集成或进行数据分析
-- 导出每小时电表数据摘要(CSV格式)
SELECT CONCAT_WS(',',TO_ISO8601(ts),device_id,region,location,CAST(AVG(voltage) AS VARCHAR(10)),CAST(AVG(current) AS VARCHAR(20)),CAST(AVG(power) AS VARCHAR(20)),CAST(SUM(power)/1000 AS VARCHAR(20)) -- 转换为kWh) AS csv_line
FROM meters
WHERE ts >= NOW - 24h
INTERVAL(1h)
ORDER BY ts;
结果示例:
csv_line
------------------------------------------------------------------------------------
2025-11-07T09:00:00+08:00,M10001,华东,上海办公楼10层1001室,220,10.2,2.25,2.25
2025-11-07T10:00:00+08:00,M10001,华东,上海办公楼10层1001室,221,10.5,2.32,2.32
2025-11-07T11:00:00+08:00,M10001,华东,上海办公楼10层1001室,222,10.3,2.28,2.28
场景 4: 生成运维工单描述
目的: 自动生成包含完整信息的工单描述,提高运维效率
-- 生成需要维护的电表工单信息
SELECT device_id,CONCAT_WS(' - ','设备ID:' || device_id,'位置:' || region || '/' || location,'问题:电压不稳定','统计周期:最近24小时','电压范围:' || CAST(MIN(voltage) AS VARCHAR(10)) || 'V~' || CAST(MAX(voltage) AS VARCHAR(10)) || 'V','异常次数:' || CAST(COUNT(*) AS VARCHAR(10)),'建议:现场检查线路') AS work_order
FROM meters
WHERE ts >= NOW - 24hAND (voltage < 210 OR voltage > 240)
GROUP BY device_id, region, location
HAVING COUNT(*) > 10
ORDER BY COUNT(*) DESC;
结果示例:
device_id | work_order
------------------------------------------------------------------------------------
M10001 | 设备ID:M10001 - 位置:华东/上海办公楼10层1001室 - 问题:电压不稳定 - 统计周期:最近24小时 - 电压范围:205V~245V - 异常次数:45 - 建议:现场检查线路
M10032 | 设备ID:M10032 - 位置:华东/上海办公楼8层801室 - 问题:电压不稳定 - 统计周期:最近24小时 - 电压范围:208V~242V - 异常次数:32 - 建议:现场检查线路
场景 5: 生成能耗报告摘要
目的: 创建易读的能耗分析报告,支持多维度查看
-- 按区域生成能耗摘要报告
SELECT region,CONCAT_WS(' | ','总用电量:' || CAST(ROUND(SUM(power)/1000, 2) AS VARCHAR(20)) || 'kWh','平均功率:' || CAST(ROUND(AVG(power), 2) AS VARCHAR(20)) || 'kW','峰值功率:' || CAST(ROUND(MAX(power), 2) AS VARCHAR(20)) || 'kW','平均电压:' || CAST(ROUND(AVG(voltage), 0) AS VARCHAR(10)) || 'V','设备数量:' || CAST(COUNT(DISTINCT device_id) AS VARCHAR(10))) AS energy_summary
FROM meters
WHERE ts >= NOW - 30d
GROUP BY region
ORDER BY SUM(power) DESC;
结果示例:
region | energy_summary
------------------------------------------------------------------------------------
华东 | 总用电量:125680.50kWh | 平均功率:2.35kW | 峰值功率:18.90kW | 平均电压:221V | 设备数量:156
华北 | 总用电量:98450.25kWh | 平均功率:3.12kW | 峰值功率:22.50kW | 平均电压:220V | 设备数量:98
华南 | 总用电量:87320.80kWh | 平均功率:2.88kW | 峰值功率:19.50kW | 平均电压:222V | 设备数量:112
场景 6: 生成设备状态标签
目的: 为监控大屏或仪表盘生成包含多个状态信息的标签
-- 生成实时设备状态标签
SELECT device_id,region,location,CONCAT_WS(' · ',CASE WHEN voltage BETWEEN 210 AND 240 THEN '✓电压正常'ELSE '✗电压异常'END,CASE WHEN power < 5 THEN '负载低'WHEN power < 10 THEN '负载中'ELSE '负载高'END,CASE WHEN phase BETWEEN -15 AND 15 THEN '功率因数正常'ELSE '功率因数异常'END,CAST(ROUND(power, 1) AS VARCHAR(10)) || 'kW') AS status_label,ts
FROM meters
WHERE ts >= NOW - 5m
ORDER BY power DESC
LIMIT 10;
结果示例:
device_id | region | location | status_label | ts
-------------------------------------------------------------------------------------------------
M20015 | 华北 | 北京数据中心3层机房A | ✓电压正常 · 负载高 · 功率因数正常 · 18.5kW | 2025-11-07 14:30:00
M10032 | 华东 | 上海办公楼8层801室 | ✓电压正常 · 负载高 · 功率因数正常 · 16.2kW | 2025-11-07 14:30:00
M10008 | 华东 | 上海办公楼5层501室 | ✗电压异常 · 负载中 · 功率因数异常 · 12.8kW | 2025-11-07 14:30:00
场景 7: 生成设备维护记录
目的: 根据设备运行状态自动生成维护建议记录
-- 生成设备健康状况报告
SELECT device_id,location,CONCAT_WS('\n','=== 设备健康报告 ===','设备编号: ' || device_id,'安装位置: ' || region || ' - ' || location,'数据时间: ' || TO_ISO8601(LAST(ts)),'--- 电能质量 ---','电压: ' || CAST(LAST(voltage) AS VARCHAR(10)) || 'V','电流: ' || CAST(ROUND(LAST(current), 2) AS VARCHAR(10)) || 'A','功率: ' || CAST(ROUND(LAST(power), 2) AS VARCHAR(10)) || 'kW','相位角: ' || CAST(ROUND(LAST(phase), 2) AS VARCHAR(10)) || '°','--- 运行状态 ---',status_msg) AS health_report
FROM meters
WHERE groupid = 1
GROUP BY device_id, region, location
ORDER BY device_id;
结果示例:
device_id | location | health_report
-------------------------------------------------------------------------------------------------
M10001 | 上海办公楼10层1001室 | === 设备健康报告 ===| | 设备编号: M10001| | 安装位置: 华东 - 上海办公楼10层1001室| | 数据时间: 2025-11-07T14:30:00+08:00| | --- 电能质量 ---| | 电压: 221V| | 电流: 10.52A| | 功率: 2.32kW| | 相位角: 5.2°| | --- 运行状态 ---| | 设备运行正常
CONCAT_WS 与 CONCAT 函数的区别
1. 分隔符处理
CONCAT 函数:
-- CONCAT 直接连接,无分隔符
SELECT CONCAT(region, location, device_id) AS result
FROM meters
LIMIT 1;
结果: 华东上海办公楼10层1001室M10001 (字符串直接拼接,无分隔符)
CONCAT_WS 函数:
-- CONCAT_WS 使用指定分隔符连接
SELECT CONCAT_WS('-', region, location, device_id) AS result
FROM meters
LIMIT 1;
结果: 华东-上海办公楼10层1001室-M10001 (使用 - 作为分隔符)
2. NULL 值处理
CONCAT 函数:
-- 插入测试数据(status_msg 为 NULL)
INSERT INTO meters_test VALUES (NOW, 10.5, 220, 5.0, 2.3, 'M10001', '华东', NULL);-- CONCAT 遇到 NULL 返回 NULL
SELECT CONCAT(region, '-', location, '-', status_msg) AS result
FROM meters_test;
结果: NULL (任一参数为 NULL,整个结果为 NULL)
CONCAT_WS 函数:
-- CONCAT_WS 自动跳过 NULL 值
SELECT CONCAT_WS('-', region, location, status_msg) AS result
FROM meters_test;
结果: 华东-上海办公楼10层1001室 (自动跳过 NULL 值的 status_msg)
3. 参数数量
CONCAT 函数:
- 最少 2 个参数
- 最多无限制(取决于系统限制)
CONCAT_WS 函数:
- 最少 3 个参数(1 个分隔符 + 2 个字符串)
- 最多 9 个参数(1 个分隔符 + 8 个字符串)
4. 使用场景对比
| 场景 | CONCAT | CONCAT_WS | 推荐 |
|---|---|---|---|
| 简单拼接固定格式 | CONCAT('设备:', device_id) | CONCAT_WS(':', '设备', device_id) | CONCAT |
| 需要统一分隔符 | CONCAT(region, '-', location, '-', device_id) | CONCAT_WS('-', region, location, device_id) | CONCAT_WS |
| 可能有 NULL 值 | 结果为 NULL | 自动跳过 NULL | CONCAT_WS |
| 生成 CSV 格式 | 需要手动添加逗号 | CONCAT_WS(',', col1, col2, col3) | CONCAT_WS |
| 路径拼接 | 需要手动添加分隔符 | CONCAT_WS('/', region, building, floor) | CONCAT_WS |
5. 实际示例对比
-- 场景:生成设备完整信息,某些字段可能为 NULL-- 使用 CONCAT(不推荐,遇到 NULL 会失败)
SELECT device_id,CONCAT(region, '-', location, '-', status_msg, '-', CAST(groupid AS VARCHAR(10))) AS info
FROM meters
WHERE device_id = 'M10001';
-- 如果 status_msg 为 NULL,整个结果为 NULL-- 使用 CONCAT_WS(推荐,自动跳过 NULL)
SELECT device_id,CONCAT_WS('-', region, location, status_msg, CAST(groupid AS VARCHAR(10))) AS info
FROM meters
WHERE device_id = 'M10001';
-- 如果 status_msg 为 NULL,结果为: 华东-上海办公楼10层1001室-1
6. 性能考虑
- CONCAT: 由于需要手动添加分隔符,参数数量较多时代码冗长
- CONCAT_WS: 代码简洁,但有参数数量限制(最多8个待连接字符串)
总结
-
使用 CONCAT 的场景:
- 简单的字符串拼接
- 不需要统一分隔符
- 确定所有字段都不为 NULL
- 需要超过 8 个字段拼接
-
使用 CONCAT_WS 的场景:
- 需要统一分隔符连接多个字段
- 字段可能包含 NULL 值,且希望跳过 NULL
- 生成 CSV、路径等格式化字符串
- 代码简洁性要求高
注意事项
- 参数限制: CONCAT_WS 最多支持 8 个待连接的字符串(加上分隔符共 9 个参数)
- 结果长度: 连接后的字符串长度会随参数数量增加,需注意不要超出系统限制(VARCHAR 最大 16384 字节)
- 性能考虑: 连接大量字符串时,会占用相应的内存空间
- 字符集: 混用不同字符集时,需要注意字节数的变化
- 数值转换: 在连接数值类型时,需要使用
CAST函数先转换为字符串类型 - 分隔符为 NULL: 如果分隔符本身为 NULL,则整个结果为 NULL
关于 TDengine
TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。
