如何在 SQL 中按业务主键聚合多行记录为单行(含多值拼接与条件汇总)

风敏吖_8277

风敏吖_8277

2026-07-22

455人浏览

原创

如何在 SQL 中按业务主键聚合多行记录为单行(含多值拼接与条件汇总)

本文介绍在不支持窗口函数或 cte 的旧版数据库(如 pervasive sql)中,通过 group by 配合条件聚合(case + sum)和字符串拼接逻辑,将同一工单的多工序记录合并为一条汇总记录,并保留各工序关键字段的结构化汇总结果。

本文介绍在不支持窗口函数或 cte 的旧版数据库(如 pervasive sql)中,通过 group by 配合条件聚合(case + sum)和字符串拼接逻辑,将同一工单的多工序记录合并为一条汇总记录,并保留各工序关键字段的结构化汇总结果。

在实际生产数据报表开发中,常遇到“一对多”关系导致的重复主键问题:例如一个工单(Job + suffix + part)对应多个工序操作(不同 workcenter、hours_estimated、hours_actual)。原始查询即使使用 DISTINCT,也无法消除因工序维度差异产生的多行——因为每行的 workcenter 或 seq 值不同。而业务需求往往要求每个工单仅返回一行,同时保留所有相关工序信息的可读性汇总,如将多个 workcenter 拼接为逗号分隔字符串,或将工时按车间类别分别求和。

由于提问环境使用的是 Pervasive SQL(不支持 STRING_AGG、GROUP_CONCAT 或 CTE),无法直接用现代 SQL 的聚合字符串函数实现字段拼接(如 STRING_AGG(workcenter, ','))。此时应优先在 SQL 层完成语义化聚合,而非依赖 PHP 数组处理——既减少网络传输量,又提升执行效率与逻辑一致性。

✅ 推荐方案:条件聚合(Conditional Aggregation)+ 分组汇总

核心思路是:不拼接原始字符串,而是按业务规则对数值型字段(如 hours_actual)进行分类汇总,对字符型字段(如 workcenter)则通过预定义映射归类到固定列。例如:

  • 将 workcenter IN ('0705','0710','0715') 统一归为 "Laser" 类别;
  • 对该类别下所有 hours_actual 求和,得到 Laser 总工时;
  • 同理定义 WaterJet、Prep、Fab 等列,实现横向展开。

这样既满足“每工单一行”的要求,又使结果具备明确业务含义,比纯字符串拼接(如 "0710,0805,0901,1520")更易后续分析与前端展示。

DBeaver Community 26.2.1
DBeaver Community 26.2.1

DBeaver Community 26.2.1 Windows x64 官方安装包,适用于数据库连接、SQL 开发、数据浏览和管理。

下载

以下是优化后的标准 SQL 模板(兼容 Pervasive、SQL Server、MySQL 5.7+ 等):

SELECT
  v_job_header.job,
  v_job_header.suffix,
  v_job_header.part,
  v_job_header.product_line AS PL,
  v_job_header.qty_order AS qty,

  -- 按车间类别汇总实际工时(数值聚合)
  SUM(CASE WHEN v_job_operations_wc.workcenter = '0750' THEN v_job_operations_wc.hours_actual ELSE 0 END) AS WaterJet,
  SUM(CASE WHEN v_job_operations_wc.workcenter IN ('0705','0710','0715') THEN v_job_operations_wc.hours_actual ELSE 0 END) AS Laser,
  SUM(CASE WHEN v_job_operations_wc.workcenter IN ('0600','0610','1006','0650','1315') THEN v_job_operations_wc.hours_actual ELSE 0 END) AS Prep,
  SUM(CASE WHEN v_job_operations_wc.workcenter IN ('1310','0755') THEN v_job_operations_wc.hours_actual ELSE 0 END) AS Machining,
  SUM(CASE WHEN v_job_operations_wc.workcenter IN ('1515','1000','1002','1003','0901','1270') THEN v_job_operations_wc.hours_actual ELSE 0 END) AS Fab,

  -- 汇总预估总工时(全局求和)
  SUM(v_job_operations_wc.hours_estimated) AS total_hours_estimated,

  -- 关联表字段(需加入 GROUP BY,避免歧义)
  gab_source_cause_codes.source,
  gab_source_cause_codes.cause

FROM v_job_header
LEFT JOIN v_job_operations_wc 
  ON v_job_operations_wc.job = v_job_header.job 
  AND v_job_header.suffix = v_job_operations_wc.suffix
LEFT JOIN gab_source_cause_codes 
  ON gab_source_cause_codes.job = v_job_operations_wc.job 
  AND gab_source_cause_codes.suffix = v_job_operations_wc.suffix 
  AND gab_source_cause_codes.seq = v_job_operations_wc.seq

WHERE 
  v_job_header.product_line = '01' 
  AND v_job_header.date_closed <h3>⚠️ 注意事项与最佳实践</h3>
  • GROUP BY 必须包含所有非聚合字段:如 job, suffix, part, PL, qty 及关联表中的 source/cause。遗漏会导致语法错误或不可预测聚合。
  • NULL 处理:CASE 表达式中建议显式写 ELSE 0(数值)或 ELSE ''(字符串),避免 SUM(NULL) 返回 NULL。
  • 性能提示:确保 v_job_operations_wc.job + suffix + seq 和 v_job_header.job + suffix 上有复合索引,大幅提升 JOIN 效率。
  • 若必须字符串拼接(如导出明细):Pervasive 不原生支持 GROUP_CONCAT,但可通过客户端(PHP)二次处理——先用 ORDER BY job,suffix,part,seq 获取有序结果,再用 array_reduce() 或 foreach 按主键分组拼接,但此方式不推荐用于大数据集(900+ 行已属临界点)。
  • 扩展性建议:将 workcenter → category 映射抽离为独立配置表(如 wc_category_map),使 SQL 更灵活、易维护。

综上,在受限数据库环境下,放弃“字符串拼接幻想”,转向基于业务逻辑的条件聚合建模,是兼顾正确性、性能与可维护性的最优解。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

数据库

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4823

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

991

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1269

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6841

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3543

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6840

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

9501

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1290

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1132

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
DBeaver生态工具dbvr官方手册
DBeaver生态工具dbvr官方手册

共0课时 | 0人学习

DBeaver SQL编辑器使用手册
DBeaver SQL编辑器使用手册

共0课时 | 0人学习

DBeaver官方文档中心
DBeaver官方文档中心

共0课时 | 0人学习