2012-07-31 74 views
2

我試圖編寫一個連接多個一對多表的SELECT查詢。命名爲A表支出既有LEFT JOIN到指定的表接觸(因爲接觸可以有很多支出)和LEFT JOIN到指定的表承諾(因爲一個承諾(支付承諾)可以有多個支出(實際支付)。mysql sum multiple joins

我的問題是我怎麼能拉,列出的聯繫人,他們的承諾記錄,質押餘額(支出的走向

這裏祈願減去承諾)?總和是我得到了什麼到目前爲止:

SELECT *, (p.pl_amount - SUM(disb_amount)) as balance FROM disbursements d 
LEFT JOIN contacts c on c.c_no = d.c_no 
LEFT JOIN pledges p on d.pl_no = p.pl_no 
GROUP BY d.disb_no 
HAVING balance > 500 
ORDER BY c.c_last 

預先感謝您

+0

什麼表是'disb_amount'中的? – 2012-07-31 20:42:16

回答

0

什麼,你可能會想要做的就是把contactsFROM子句中,而不是在一個LEFT JOIN因爲你仍然想即使檢索聯繫人時,他們沒有任何付款/承諾。

而且因爲你似乎只希望有一個認捐餘額>500接觸,一個LEFT JOIN是沒有必要,除非你也想找回沒有任何質押或有一個平衡>500接觸。我用了一個普通(內部)JOIN代替:

試試這個:

SELECT c.*, 
      p.*, 
      COALESCE(p.pl_amount - pd.disb_sum, 0) AS pledge_balance 
FROM  contacts c 
LEFT JOIN disbursements d ON c.c_no = d.c_no 
LEFT JOIN pledges p ON d.pl_no = p.pl_no 
LEFT JOIN (
      SELECT pl_no, SUM(disb_amount) AS disb_sum 
      FROM  disbursements 
      GROUP BY pl_no 
     ) pd ON p.pl_no = pd.pl_no 
WHERE  p.pl_no IS NULL OR 
      p.pl_amount - pd.disb_sum > 500 
ORDER BY c.c_last 
+0

謝謝!這幾乎是我需要的。如果沒有與祈願相關的支出,我只需要弄清楚如何顯示'p'的'pledge_balance'。 – Ennui 2012-07-31 22:52:14

+0

@Ennui,看到我更新的解決方案。我相信它應該適用於你想要做的事情。它只會獲得質押餘額大於500的聯繫人,或者根本沒有任何支出的聯繫人。 – 2012-07-31 22:57:39

+0

完美。謝謝! – Ennui 2012-07-31 23:13:03

0

我認爲你可以簡化這個問題。如果我理解正確,您的支出取決於您的承諾(如果沒有承諾,則不支付)。如果這是真的,那麼你可以做這樣的事情:

select 
    p.pl_no, p.pl_amount - sum(disb_amount) as balance 
from 
    pledges as p 
    left join disbursements as d on p.pl_no = d.pl_no 
group by 
    p.pl_no 
having 
    p.pl_amount - sum(disb_amount) > 500; 

如果您需要完整的信息(聯繫人,認捐和支出),那麼你必須認爲這是一個多步驟的問題:

  1. 首先需要的承諾的平衡
  2. 您需要的承諾
  3. 您需要的這個完整的信息相關聯的聯繫人記錄

所以,上面的查詢提供您所需要的步驟1中,您可以創建一個臨時表與該信息的信息:

Create temporary table temp_pledge_balance 
select 
    p.pl_no, p.pl_amount - sum(disb_amount) as balance 
from 
    pledges as p 
    left join disbursements as d on p.pl_no = d.pl_no 
group by 
    p.pl_no; 

我建議你這個指數表,加快後續步驟:

Alter table temp_pledge_balance 
    add index pl_no (pl_no); 

現在,對於步驟2:

create temporary table temp_contacts 
select c.*, p.pl_no 
from 
    temp_pledge_balance as pb 
    inner join pledges as p on pb.pl_no=p.pl_no 
    inner join contacts as c on p.c_no = c.c_no; 
alter temp_contacts 
    add index c_no(c_no); 

最後,對於步驟3:

select 
    tc.*, pb.*, p.*, d.* 
from 
    temp_contacts as tc 
    left join disbursements as d on tc.c_no = d.c_no 
    left join pledges as p on d.pl_no = p.pl_no 
    left join temp_pledge_balance as pb on p.pl_no = pb.p_no 
where 
    pb.balance > 500 

一個棘手的解決方案,但它可能會幫助你。