MS SQL多表关联查询SUM()聚合仅统计最新记录工时的问题
未完成工单预估工时统计SQL问题解决
问题描述
需要统计每台设备对应未完成工单的预估总工时,需关联change、part、completed三张表获取最新变更记录的工时值。目前已能查询到待求和的工时列表,但尝试使用SUM()函数进行汇总时始终抛出聚合错误,原有SQL代码如下:
SELECT (SELECT TOP 1 change.hours FROM change WHERE change.id = part.id ORDER BY change.timeStamp DESC) as 'Hours' FROM change INNER JOIN part ON (part.id = change.id) INNER JOIN completed ON (part.id = completed.id) WHERE part.id NOT IN (SELECT completed.id FROM completed WHERE completed.completed = 1) and (SELECT TOP 1 change.machine FROM change WHERE part.id = change.id ORDER BY change.timeStamp DESC ) = :machine GROUP BY change.id, part.id
预期输出
- 设备1总工时12小时
- 设备2总工时18小时
- 设备3总工时18小时
相关表结构与数据
part表
| id | number | description(描述) | job(工单编号) |
|---|---|---|---|
| 14 | 40023-10-100-10-03 | 底座 | 40023 |
| 15 | 40023-10-200-10-03 | 底座 | 40023 |
| 16 | 40024-10-100-10-01 | 传感器支架 | 40024 |
| 17 | 40024-10-100-10-02 | 侧件 | 40024 |
| 18 | 40025-10-100-10-01 | 输送机固定件 | 40025 |
| 19 | 40025-10-200-00-01 | 零件 | 40025 |
| 20 | 40026-10-400-00-01 | 电机安装座 | 40026 |
| 21 | 40026-10-200-10-10 | 三角机械臂 | 40026 |
| 22 | 40023-10-200-10-03 | 底座 | 40023 |
change表1
| id | qty(数量) | hours(工时) | machine(设备号) | operator(操作员) | startTime(开始时间) | stopTime(结束时间) | completed(是否完成) | date(日期) | timeStamp(时间戳) |
|---|---|---|---|---|---|---|---|---|---|
| 14 | 0 | 0 | 2 | 2 | NULL | NULL | 否 | NULL | 2021-10-28 00:00:00.000 |
| 15 | 0 | 0 | 4 | 3 | NULL | NULL | 否 | NULL | 2021-10-28 11:01:41.427 |
| 19 | 0 | 0 | 3 | 1 | NULL | NULL | 否 | NULL | 2021-10-28 11:10:50.730 |
| 18 | 0 | 0 | 2 | 3 | NULL | NULL | 否 | NULL | 2021-10-28 11:13:46.213 |
| 16 | 3 | 2.5 | 2 | 2 | NULL | NULL | 否 | 2021-10-27 | 2021-10-28 13:41:12.393 |
| 16 | 3 | 2.5 | 2 | 2 | NULL | NULL | 否 | 2021-10-27 | 2021-10-28 13:41:12.393 |
| 15 | 1 | 9 | 3 | 3 | NULL | NULL | 是 | 2021-10-29 | 2021-10-28 21:38:44.883 |
| 14 | 0 | 0 | 1 | 1 | NULL | NULL | 否 | NULL | 2021-11-01 10:36:43.223 |
| 14 | 0 | 0 | 1 | 1 | NULL | NULL | 否 | NULL | 2021-11-01 10:37:47.153 |
| 16 | 1 | 0.5 | 2 | 2 | NULL | NULL | 否 | 2021-11-01 | 2021-11-01 11:12:06.840 |
| 21 | 0 | 0 | 1 | 1 | NULL | NULL | 否 | NULL | 2021-11-01 11:45:30.050 |
| 20 | 0 | 0 | 2 | 3 | NULL | NULL | 否 | NULL | 2021-11-10 10:44:00.000 |
| 23 | 0 | 0 | 0 | 0 | NULL | NULL | 是 | 2021-11-02 | 2021-11-02 16:26:18.583 |
| 16 | 1 | 1 | 2 | 2 | NULL | NULL | 否 | 2021-11-01 | 2021-11-01 11:03:44.160 |
| 17 | 0 | 0 | 2 | 2 | NULL | NULL | 否 | NULL | 2021-10-28 11:25:03.967 |
| 17 | 0 | 0 | 1 | 1 | NULL | NULL | 否 | NULL | 2021-11-01 10:40:36.850 |
| 17 | 0 | 0 | 1 | 1 | NULL | NULL | 否 | NULL | 2021-11-01 10:42:56.350 |
| 22 | 0 | 0 | 3 | 2 | NULL | NULL | 否 | NULL | 2021-11-02 11:58:08.360 |
| 17 | 0 | 0 | 1 | 2 | NULL | NULL | 否 | NULL | 2021-11-01 10:43:44.273 |
| 14 | 0 | 0 | 1 | 1 | NULL | NULL | 否 | NULL | 2021-11-01 10:44:23.440 |
| 14 | 0 | 0 | 1 | 1 | NULL | NULL | 否 | NULL | 2021-11-02 12:57:06.810 |
change表2
| id | hours(工时) | qty(数量) | machine(设备号) | operator(操作员) | notes(备注) | rush(是否加急) | timeStamp(时间戳) |
|---|---|---|---|---|---|---|---|
| 14 | 2 | 3 | 2 | 1 | 否 | 2021-10-28 10:48:54.910 | |
| 15 | 10 | 1 | 3 | 2 | 否 | 2021-10-28 10:49:47.643 | |
| 16 | 7 | 10 | 2 | 3 | 缺料 | 是 | 2021-10-28 10:50:33.880 |
| 17 | 4 | 2 | 1 | 1 | 否 | 2021-10-28 00:00:00.000 | |
| 18 | 5 | 1 | 2 | 2 | 否 | 2021-10-28 10:53:15.470 | |
| 19 | 8 | 3 | 3 | 3 | 否 | 2021-10-28 11:10:50.573 | |
| 14 | 3 | 4 | 1 | 1 | 等待铣床 | 否 | 2021-10-29 08:12:00.000 |
| 17 | 4 | 2 | 1 | 1 | 是 | 2021-11-01 10:40:36.707 | |
| 17 | 4 | 2 | 1 | 1 | 是 | 2021-11-01 10:42:56.150 | |
| 16 | 8 | 10 | 2 | 3 | 缺料 | 否 | 2021-11-01 10:43:29.930 |
| 17 | 4 | 2 | 1 | 2 | 否 | 2021-11-01 10:43:44.047 | |
| 14 | 3 | 4 | 1 | 1 | 否 | 2021-11-01 10:44:23.317 | |
| 20 | 2 | 4 | 2 | 3 | 否 | 2021-11-01 11:44:10.257 | |
| 21 | 5 | 3 | 1 | 1 | 缺料 | 是 | 2021-11-01 11:45:29.927 |
| 22 | 10 | 1 | 3 | 2 | 否 | 2021-11-02 11:58:08.220 | |
| 14 | 3 | 4 | 1 | 1 | 是 | 2021-11-02 12:57:06.683 | |
| 14 | 4 | 2 | 1 | 1 | 等待钻头 | 否 | 2021-10-29 00:00:00.000 |
| 14 | 3 | 4 | 1 | 1 | 铣床型号错误,需重新采购 | 否 | 2021-11-01 10:36:42.997 |
| 14 | 3 | 4 | 1 | 1 | 铣床型号错误,需重新采购 | 否 | 2021-11-01 10:37:46.983 |
修正方案
原有SQL报错的原因是直接对嵌套子查询的结果聚合时,聚合维度与分组逻辑不匹配。可以先通过窗口函数拿到每个part id对应的最新change记录,再过滤未完成工单后按设备求和,修正后的SQL如下(兼容SQL Server语法,适配你提供的TOP 1写法):
-- 先获取每个part id对应的最新变更工时和所属设备 WITH latest_change AS ( SELECT id, hours, machine, ROW_NUMBER() OVER (PARTITION BY id ORDER BY timeStamp DESC) AS rn FROM change ) SELECT CONCAT('设备', lc.machine, '总工时', SUM(lc.hours), '小时') AS result FROM latest_change lc INNER JOIN part p ON lc.id = p.id INNER JOIN completed c ON p.id = c.id WHERE lc.rn = 1 -- 只取最新的变更记录 AND c.completed != 1 -- 过滤未完成工单 GROUP BY lc.machine ORDER BY lc.machine
如果需要查询单台设备的总工时,直接在WHERE条件中添加lc.machine = :machine即可,返回结果就是对应设备的单值总工时,可直接用于GUI展示。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

