2013-02-28 52 views
0

我正在嘗試進行報告。它應該給我一個特定客戶的機器清單以及放入該機器的小時數和材料總和。具有多個左連接的錯誤值(MySQL)

在下面的例子中,我選擇不同領域的材料和小時數的總和,以使問題更清楚。但我真的想把這些材料總結一小時,然後在機器領域分組。

我可以查詢機器列表和小時數沒有問題的成本。

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`; 

然後小時和材料值都不正確。

我讀過其他線程,其中有相似問題的人可以通過將其拆分爲多個查詢或子查詢來解決此問題。但我認爲在這種情況下這是不可能的。

任何幫助表示讚賞。

//約翰

回答

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 
+0

這是真棒單行。奇蹟般有效。 – John 2013-02-28 19:38:09

+0

我不知道你可以加入子查詢。有很多東西需要學習。無論如何...再次感謝。 – John 2013-02-28 19:39:20

+0

你如何構建這樣的查詢?你只是從上到下寫下它們,還是你有一個方法呢? – John 2013-02-28 19:45:11