基于s_case_id高效拼接多行customString字段值的实现方案
高效处理千万级数据:按s_case_id合并重复前缀的customString
核心思路
同一s_case_id下的customString日期前缀完全重复,只需保留任意一条的前缀,再将所有记录的非前缀内容聚合拼接即可。关键是用数据库原生聚合函数替代遍历/游标,同时依赖索引提升分组效率。
前提假设
假设customString的日期前缀为固定格式(如YYYY-MM-DD 业务内容,日期与内容用空格分隔),若你的前缀分隔符不同(冒号、下划线等),只需调整字符串拆分逻辑。
分数据库实现方案
1. MySQL/MariaDB
SELECT s_case_id, -- 取该组任意一条的日期前缀(因前缀重复,MIN/MAX均可) SUBSTRING_INDEX(MIN(customString), ' ', 1) AS date_prefix, -- 聚合所有非前缀内容,逗号分隔 GROUP_CONCAT(SUBSTRING(customString, LENGTH(SUBSTRING_INDEX(customString, ' ', 1)) + 2) SEPARATOR ', ') AS merged_content, -- 拼接最终结果 CONCAT( SUBSTRING_INDEX(MIN(customString), ' ', 1), ' ', GROUP_CONCAT(SUBSTRING(customString, LENGTH(SUBSTRING_INDEX(customString, ' ', 1)) + 2) SEPARATOR ', ') ) AS final_customString FROM your_temp_table GROUP BY s_case_id;
优化点:
- 给
s_case_id创建单列索引:CREATE INDEX idx_s_case_id ON your_temp_table(s_case_id);,大幅提升分组性能。 - 若
GROUP_CONCAT结果过长,临时调整配置:SET SESSION group_concat_max_len = 102400;(根据实际内容长度设置)。
2. PostgreSQL
WITH split_data AS ( SELECT s_case_id, -- 拆分日期前缀与业务内容 SPLIT_PART(customString, ' ', 1) AS date_prefix, SPLIT_PART(customString, ' ', 2) AS content_part FROM your_temp_table ) SELECT s_case_id, MAX(date_prefix) AS date_prefix, STRING_AGG(content_part, ', ') AS merged_content, CONCAT(MAX(date_prefix), ' ', STRING_AGG(content_part, ', ')) AS final_customString FROM split_data GROUP BY s_case_id;
优化点:
- 给
s_case_id创建索引:CREATE INDEX idx_s_case_id ON your_temp_table(s_case_id);。 - 若存在空内容,可加
WHERE content_part IS NOT NULL过滤无效数据。
3. SQL Server(2017+)
WITH split_data AS ( SELECT s_case_id, SUBSTRING(customString, 1, CHARINDEX(' ', customString) - 1) AS date_prefix, SUBSTRING(customString, CHARINDEX(' ', customString) + 1, LEN(customString)) AS content_part FROM your_temp_table ) SELECT s_case_id, MAX(date_prefix) AS date_prefix, STRING_AGG(content_part, ', ') AS merged_content, CONCAT(MAX(date_prefix), ' ', STRING_AGG(content_part, ', ')) AS final_customString FROM split_data GROUP BY s_case_id;
优化点:
- 创建
s_case_id非聚集索引:CREATE NONCLUSTERED INDEX idx_s_case_id ON your_temp_table(s_case_id);。 - 若使用2017以下版本,用
STUFF+FOR XML PATH替代STRING_AGG(写法见下方备注)。
性能注意事项
- 索引优先:
s_case_id的索引是处理千万级数据的核心,无索引会触发全表扫描,速度极慢。 - 避免重复计算:提前用CTE/子查询拆分字段,不要在聚合函数中重复执行字符串拆分逻辑。
- 分批处理:若单次聚合内存压力大,按
s_case_id范围分批执行(如WHERE s_case_id BETWEEN 'xxx' AND 'yyy'),再合并结果。 - 验证前缀一致性:先确认同一
s_case_id下前缀无差异,避免结果错误:
SELECT s_case_id, COUNT(DISTINCT SUBSTRING_INDEX(customString, ' ', 1)) AS prefix_count FROM your_temp_table GROUP BY s_case_id HAVING prefix_count > 1;
若返回非空结果,需先处理前缀不一致的异常数据。
内容的提问来源于stack exchange,提问作者JacobPelley
相关产品推荐
相关产品推荐

