2016-07-06 163 views
0

我有一個表交貨和一個表訂單。幾個訂單可以鏈接到交付。前幾天,我問了一個question關於如何獲得特定交付訂單金額的總和,並迅速顯示如何。 (再次感謝。)SUM和GROUP BY問題

現在我們已經添加了結算表,並且就像訂單一樣,可以有多個結算鏈接到一個交付(通過交付ID,就像訂單一樣),而我試圖獲得他們的價值總和。我想我會使用相同的策略和左加入結算表,但問題是,當只有一個結算鏈接到特定的交付時,SUM(s.amount)返回實際值的兩倍。

我試着玩弄GROUP BY無濟於事。任何人都可以告訴我我做錯了什麼?

提前致謝!

PS:這是我一直在使用,當只有一個結算返回結算量的兩倍值查詢:

SELECT 
    d.id, 
    SUM(o.goods_amount) AS amount, 
    SUM(s.amount) AS settlementAmount, 
FROM delivery d 
LEFT JOIN order o 
    ON d.id = o.delivery_id 
LEFT JOIN settlement s 
    ON d.id = s.delivery_id 
WHERE d.id = *deliveryId* 
GROUP BY d.id; 
+0

最可能的解釋是部分交叉產品。結算的一行從交付和/或訂單中匹配到多行。然後,在執行彙總時,結算中有多行復制行。刪除GROUP BY和SUM聚合,運行查詢,您將看到發生了什麼。 – spencer7593

+0

我試着在沒有GROUP BY和SUM的情況下運行gthe查詢,並在交付時測試了2個訂單和1個結算附加到它。就像你說的那樣,它返回2行,一行包含order1的order_amount和settlement_amount,另一行包含order2的order_amount和相同的settlement_amount。這就解釋了爲什麼SUM給了我一個雙重價值。有什麼辦法可以解決這個問題嗎? – Feanor

+0

一種方法是將每個表的聚合(SUM)分開進行,作爲單獨的查詢。要合併這些查詢,請將每個查詢包裝在parens中,然後在另一個查詢中使用整個子查詢代替表引用。 – spencer7593

回答

1

正如斯賓塞評論說的,你是得到一種交叉連接的結果。讓我們看看這個示例數據。

Delivery Table 
ID Delivered_On 
1 2016-07-01 
2 2016-07-02 

Orders Table 
id Deliveries_id Amount 
1 1    100 
2 1    200 
3 1    300 
4 2    75 

Now your Settlements table 
Settlements Table 
id Delivery_id Amount 
1 1    525 (explicitly wrong amount to show result) 
2 1    75 

您的查詢是根據交貨ID進行彙總,但(左)已加入訂單表和結算表。因此,每張表中存在多個記錄將交叉連接,因此對於Delivery ID = 1,您有3個訂單,但有1個結算。因此,結算記錄也將被加入到每個訂單表中,而不僅僅是交貨表格,因此給出3 * 525或1575加3 * 75 = 225美元的結果,總共1800美元。您的訂單總額將適當爲600美元。

要解決這個問題,您可能需要預先聚合每個輔助表,以便每個傳遞僅返回1個摘要記錄並加入THOSE結果。爲了防止查詢所有訂單和結算,我將加入到交貨表中,以確定所有訂單和結算的日期範圍。

SELECT 
     d.id AS delivery_id, 
     sumOrd.Amount as OrderAmount, 
     sumStl.Amount as SettlementAmount 
    from 
     delivery d 

     LEFT JOIN 
     (select 
       d2.id, 
       SUM(o.amount) AS OrderAmount 
       from 
       delivery d2 
        JOIN order o 
         ON d2.id = o.deliveries_id 
       WHERE 
        d2.delivered_on >= '2016-06-10' 
       and d2.delivered_on < '2016-06-11' 
       GROUP BY 
       d2.id) sumOrd 
      on d.id = sumOrd.id 

     LEFT JOIN 
     (select 
       d2.id, 
       SUM(s.amount) AS SettlementAmount 
       from 
       delivery d2 
        JOIN Settlement s 
         ON d2.id = s.delivery_id 
       WHERE 
        d2.delivered_on >= '2016-06-10' 
       and d2.delivered_on < '2016-06-11' 
       GROUP BY 
       d2.id) sumStl 
      on d.id = sumStl.id 
    where 
      d.delivered_on >= '2016-06-10' 
     and d.delivered_on < '2016-06-11' 
+0

這樣做的伎倆,謝謝! – Feanor

0

首先確認您使用下面的查詢得到正確的結果

SELECT 
      d.id, 
      IFNULL(o.goods_amount,0) AS amount, 
      IFNULL(s.amount,0) AS settlementAmount, 
     FROM delivery d 
     LEFT JOIN order o 
      ON d.id = o.delivery_id 
     LEFT JOIN settlement s 
      ON d.id = s.delivery_id 
     WHERE d.id = *deliveryId* 

然後請檢查這個查詢

SELECT 
     d.id, 
     SUM(IFNULL(o.goods_amount,0)) AS amount, 
     SUM(IFNULL(s.amount,0)) AS settlementAmount, 
    FROM delivery d 
    LEFT JOIN order o 
     ON d.id = o.delivery_id 
    LEFT JOIN settlement s 
     ON d.id = s.delivery_id 
    WHERE d.id = *deliveryId* 
    GROUP BY d.id; 
+0

這給了我恐怕同樣的結果。就像我在給spencer7593的評論中所寫的那樣,在交付2個訂單和1個結算的情況下,我得到兩個記錄,一個記錄來自訂單1,另一個記錄訂單2的金額,但他們都有結算金額。: -/ – Feanor

+0

@Feanor是否檢查過第一個查詢,並且可以添加結果集 –

+0

確定 記錄1:id:7887,金額:15.80,結算金額:19.08 記錄2:id:7887,金額:9.00,settlementAmount: 19.08 – Feanor