mysql求和多个连接

时间:2012-07-31 20:05:03

标签: mysql sql

我正在尝试编写一个连接多个一对多表的SELECT查询。名为支出的表格同时包含LEFT JOIN到名为联系人的表格(因为联系人可以有多笔付款)和LEFT JOIN到表格名为承诺(因为承诺(付款承诺)可以有多笔付款(实际付款)。

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

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

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

提前谢谢

2 个答案:

答案 0 :(得分:0)

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

此外,因为您似乎只想要具有承诺余额的联系人> 500,除非您还想要检索没有任何承诺或有余额>的联系人,否则不需要LEFT JOIN500。我使用常规(内部)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

答案 1 :(得分: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. 您需要此记录的完整信息
  4. 因此,上面的查询为您提供了步骤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
    

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