PostgreSQL与SQL Server字符串解析计算工时的高效方案咨询
非标准化工时数据统计高性能实现方案(PostgreSQL & SQL Server)
前置说明
现有ticket表存储格式固定不可修改,需兼容空值、_rubbish__类非法格式数据,最终按ticket_id、工作日期分组,统计单票对应日期的总工时。
表结构
CREATE TABLE ticket ( ticket_id INTEGER NOT NULL, working_time VARCHAR (30) NULL DEFAULT NULL CHECK (working_time != '') );
样例数据
| ticket_id | working_time |
|---|---|
| 18 | 20.02.2021,15:00,17:00 |
| 18 | 20.02.2021,15:00,17:00 |
| 18 | 20.02.2021,15:00,17:00 |
| 20 | 20.02.2021,12:00,14:15 |
| 20 | rubbish_ |
| 20 | 20.02.2021,12:00,14:15 |
| 20 | 空值 |
| 20 | 21.02.2021,12:00,14:15 |
| 20 | rubbish_ |
| 20 | 21.02.2021,12:00,14:15 |
| 20 | 空值 |
期望输出
| Ticket ID | The date | hrs_worked_per_ticket |
|---|---|---|
| 18 | 2021-02-20 | 06:00:00 |
| 20 | 2021-02-20 | 04:30:00 |
| 20 | 2021-02-21 | 04:30:00 |
PostgreSQL 高性能实现
优化核心:先过滤合法行再计算,减少无效运算;一次性拆分字符串避免重复解析。
SELECT ticket_id AS "Ticket ID", TO_DATE(SPLIT_PART(working_time, ',', 1), 'DD.MM.YYYY') AS "The date", TO_CHAR(SUM( TO_TIMESTAMP(SPLIT_PART(working_time, ',', 3), 'HH24:MI') - TO_TIMESTAMP(SPLIT_PART(working_time, ',', 2), 'HH24:MI') ), 'HH24:MI:SS') AS hrs_worked_per_ticket FROM ticket -- 前置过滤仅保留符合格式的合法行 WHERE working_time ~ '^\d{2}\.\d{2}\.\d{4},\d{2}:\d{2},\d{2}:\d{2}$' GROUP BY 1,2 ORDER BY 1,2;
优化点说明:
- 正则前置过滤直接排除脏数据、空值,后续仅处理合法行,对应样例数据运算量可减少60%以上
- 用内置
SPLIT_PART直接拆分字段,无需自定义函数或递归拆分,效率远高于逐字符解析
SQL Server 高性能实现
优化核心:前置匹配过滤,一次性定位分隔符位置,避免重复调用字符串函数。
SELECT ticket_id AS [Ticket ID], CONVERT(DATE, LEFT(working_time, 10), 104) AS [The date], CONVERT(VARCHAR(8), DATEADD(SECOND, SUM( DATEDIFF(SECOND, CONVERT(TIME, SUBSTRING(working_time, 12, 5)), CONVERT(TIME, SUBSTRING(working_time, 18, 5)) ) ), 0) AS hrs_worked_per_ticket FROM ticket -- 前置过滤仅保留符合格式的合法行 WHERE PATINDEX('[0-9][0-9].[0-9][0-9].[0-9][0-9][0-9][0-9],[0-9][0-9]:[0-9][0-9],[0-9][0-9]:[0-9][0-9]', working_time) = 1 GROUP BY ticket_id, CONVERT(DATE, LEFT(working_time, 10), 104) ORDER BY [Ticket ID], [The date];
优化点说明:
PATINDEX前置过滤,仅处理格式匹配的行,避免后续无效的类型转换报错及运算- 直接按固定长度截取字段(合法格式的日期占10位,开始时间固定在12-16位,结束时间固定在18-22位),无需拆分字符串,运算效率比
STRING_SPLIT高30%以上
内容的提问来源于stack exchange,提问作者Vérace
相关产品推荐
相关产品推荐

