2

我正在尝试编写一个SELECT连接多个一对多表的查询。一个名为 disbursements 的表一个 LEFT JOIN to 一个名为contacts的表(因为一个联系人可以有很多付款)和一个 LEFT JOIN to 一个名为prostments的表(因为一个承诺(付款承诺)可以有多个付款(实际付款)。

我的问题是如何提取列出联系人、他们的承诺和承诺余额(从承诺中减去承诺支付的总和)的记录?

这是我到目前为止得到的:

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

先感谢您

4

2 回答 2

0

您可能想要做的是将contacts表放在FROM子句中而不是放在 a 中,LEFT JOIN因为即使他们没有任何付款/承诺,您仍然想检索联系人。

此外,由于您似乎只想要具有承诺余额 > 的联系人,因此 a500不是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
于 2012-07-31T20:46:06.950 回答
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

一个棘手的解决方案,但它可能会对您有所帮助。

于 2012-07-31T20:53:36.057 回答