0

我正在尝试做一个报告。它应该给我一份特定客户的机器清单以及投入该机器的时间和材料的总和。

在下面的例子中,我选择了不同领域的材料和时间的总和,以使问题更清楚。但我真的想把材料加起来一个小时,然后按机器字段对它们进行分组。

我可以毫无问题地查询机器列表和工时成本。

SELECT CONCAT(`customer`.`PREFIX`, `wo`.`machine_id`) AS `machine`, 
       ROUND(COALESCE(SUM(`wohours`.`length` * `wohours`.`price`), 0), 2) AS `hours`

FROM `wo`
JOIN `customer` ON `customer`.`id`=`wo`.`customer_id`
LEFT JOIN `wohours` ON `wohours`.`wo_id`=`wo`.`id` AND `wohours`.`wo_customer_id`=`wo`.`customer_id` 
                    AND `wohours`.`wo_machine_id`=`wo`.`machine_id` AND `wohours`.`date`>=(CURDATE() - INTERVAL DAY(CURDATE() - INTERVAL 1 DAY) DAY) - INTERVAL 11 MONTH

WHERE `wo`.`customer_id`=1
GROUP BY `wo`.`machine_id`;

这给了我几个小时的正确值。但是当我添加这样的材料时:

SELECT CONCAT(`customer`.`PREFIX`, `wo`.`machine_id`) AS `machine`, 
       ROUND(COALESCE(SUM(`wohours`.`length` * `wohours`.`price`), 0), 2) AS `hours`,
       ROUND(COALESCE(SUM(`womaterial`.`multiplier` * `womaterial`.`price`), 0), 2) AS `material`

FROM `wo`
JOIN `customer` ON `customer`.`id`=`wo`.`customer_id`
LEFT JOIN `wohours` ON `wohours`.`wo_id`=`wo`.`id` AND `wohours`.`wo_customer_id`=`wo`.`customer_id` 
           AND `wohours`.`wo_machine_id`=`wo`.`machine_id` AND `wohours`.`date`>=(CURDATE() - INTERVAL DAY(CURDATE() - INTERVAL 1 DAY) DAY) - INTERVAL 11 MONTH
LEFT JOIN `womaterial` ON `womaterial`.`wo_id`=`wo`.`id` AND `womaterial`.`wo_customer_id`=`wo`.`customer_id` 
           AND `womaterial`.`wo_machine_id`=`wo`.`machine_id` AND `wohours`.`date`>=(CURDATE() - INTERVAL DAY(CURDATE() - INTERVAL 1 DAY) DAY) - INTERVAL 11 MONTH

WHERE `wo`.`customer_id`=1
GROUP BY `wo`.`machine_id`;

那么小时和材料值都不正确。

我读过其他线程,有类似问题的人可以通过将其拆分为多个查询或子查询来解决此问题。但我认为在这种情况下这是不可能的。

任何帮助表示赞赏。

//约翰

4

1 回答 1

1

您的其他阅读是正确的。您需要将它们放入自己的“子查询”中以进行连接。您可能获得无效值的原因是材料表每台机器有多个记录,因此导致原始基于小时的笛卡尔结果。而且您不知道哪个有很多而不是只有一个,这使它看起来不正确。

所以,我已经写了,每个用于预聚合 woHours 和 woMaterial 的最内层查询都会为每个“wo_id 和 machine_id”生成一条记录,以便在完成后连接回 wo 表。这些查询中的每一个都具有您尝试为其运行的单个客户 ID 的条件。

然后,当重新加入工作订单 (wo) 表时,它会抓取所有记录并应用 ROUND() 和 COALESCE(),以防不存在此类时间或材料。所以这是类似的回归

WO    Machine ID    Machine   Hours   Material
1     1             CustX 1   2       0
2     4             CustY 4   2.5     6.5
3     4             CustY 4   1.2     .5
4     1             CustX 1   1.5     1.2

最后,您现在可以将所有这些条目的 SUM() 汇总到每个机器 ID 的一行中

Machine   Hours   Material
CustX 1   3.5     1.2
CustY 4   3.7     7.0


SELECT
      AllWO.Machine,
      SUM( AllWO.Hours ) Hours,
      SUM( AllWO.Material ) Material
   from
      ( SELECT
              wo.wo_id,
              wo.Machine_ID, 
              CONCAT(customer.PREFIX, wo.machine_id) AS machine, 
              ROUND( COALESCE( PreSumHours.MachineHours, 0), 2) AS hours,
              ROUND( COALESCE( PreSumMaterial.materialHours, 0), 2) AS material
           FROM 
              wo
                 JOIN customer 
                    ON wo.customer_id = customer.id

                 LEFT JOIN ( select wohours.wo_id,
                                    wohours.wo_machine_id,
                                    SUM( wohours.length * wohours.price ) as machinehours
                                from
                                   wohours 
                                where
                                       wohours.wo_customer_id = 1
                                   AND wohours.date >= ( CURDATE() - INTERVAL DAY( CURDATE() - INTERVAL 1 DAY) DAY) - INTERVAL 11 MONTH
                                group by
                                   wohours.wo_id,
                                   wohours.wo_machine_id ) as PreSumHours
                    ON wo.id = PreSumHours.wo_id 
                    AND wo.machine_id = PreSumHours.wo_machine_id 

                 LEFT JOIN ( select womaterial.wo_id,
                                    womaterial.wo_machine_id,
                                    SUM( womaterial.length * womaterial.price ) as materialHours
                                from
                                   womaterial
                                where
                                       womaterial.wo_customer_id = 1
                                   AND womaterial.date >= ( CURDATE() - INTERVAL DAY( CURDATE() - INTERVAL 1 DAY) DAY) - INTERVAL 11 MONTH
                                group by
                                   womaterial.wo_id,
                                   womaterial.wo_machine_id ) as PreSumMaterial
                    ON wo.id = PreSumMaterial.wo_id 
                    AND wo.machine_id = PreSumMaterial.wo_machine_id 
           WHERE 
              wo.customer_id = 1 ) AllWO
   group by
      AllWO.Machine_ID
于 2013-02-28T19:19:28.017 回答