【问题标题】:expecting result is not coming from mysql INNER JOIN预期结果不是来自 mysql INNER JOIN
【发布时间】:2015-04-18 16:48:28
【问题描述】:

我有以下两个表:

table: loan
--------------------------------------------------------
 id | advance_id | loan_amount | deposit_amount | date
--------------------------------------------------------
 1 | 22556678 | 5000 | 0 | 2015-02-06
--------------------------------------------------------

table: advance
--------------------------------------------------------
id | advance_id | advance_amount | purpose | date
--------------------------------------------------------
 1 | 22556678 | 20000 | purchase | 2015-01-30
 2 | 22556678 | 10000 | purchase | 2015-01-31
--------------------------------------------------------

我的代码是:

SELECT a.advance_id, sum(a.advance_amount) as adv_amount, a.purpose, a.date, sum(l.loan_amount) as loan_amount FROM advance as a INNER JOIN loan as l ON a.advance_id=l.advance_id GROUP BY a.advance_id HAVING sum(l.loan_amount)-sum(l.deposit_amount)>0

说明: 表'advance'是用于预付的表,表'loan'是用于贷款账户的表。为同一目的预付可以不止一次(这里是为了购买产品)。每个预付款都由一个预付款 ID 标识。由于两个预付款用于同一目的(此处用于购买产品),它们将具有相同的 Advance_id。另一方面,贷款是针对任何预付款进行的。也可以针对同一预付款多次贷款。如果任何贷款将被偿还,它将被插入到advance_id的deposit_amount列中。

在loan_page.php 中,只有在任何贷款未支付/未调整时才会显示贷款。为了识别它,我必须通过以下代码针对相同的预付款 ID 计算贷款和存款列:

GROUP BY a.advance_id HAVING sum(l.loan_amount)-sum(l.deposit_amount)>0

如果有任何贷款未偿还,我必须确定每个Advance_id 获得了多少贷款。所以我还必须选择以下内容:

sum(l.loan_amount)

我获取的输出将是:

echo 'Total loan Amount: '.$row['loan_amount'].'<br />';
echo 'Advance ID: '.$row['advance_id'].'<br />';
echo 'Advance Amount: '.$row['adv_amount'].'<br />';
echo 'Purpose of Advance: '.$row['purpose'];

上面的代码运行良好,除了总贷款金额是双倍(在这种情况下为 10000)虽然它将是 5000。我认为我的 mysql 查询的 GROUP BY 或 HAVING 子句有错误。

请告诉我,如何更正代码以使 sum(l.loan_amount) 在这种情况下为 5000,而不是 10000。

【问题讨论】:

    标签: mysql group-by inner-join having


    【解决方案1】:

    loan_amount 是双倍的原因是因为您正在使用 Advance_id 在表之间进行内部连接。由于advance_id 在advance_table 中出现了两次,所以贷款行会出现两次。从视觉上看,连接会为您提供如下内容:

    | advance | loan |
    |    1    |  1   |
    |    2    |  1   |
    

    因此,当您对 l.loan_amount 进行聚合时,它将被计算两次。为了解决这个问题,我会自己对每个表进行聚合,然后将它们连接在一起。例如,只需像这样从贷款表中获取advanced_id 和 SUM(loan_amount):

    SELECT advance_id, SUM(loan_amount)
    FROM loan
    GROUP BY advance_id;
    

    我注意到您原来的HAVING 子句检查loan_amount - deposit_amount,您可以在上述查询中执行该条件:

    SELECT advance_id, SUM(loan_amount) AS totalLoan
    FROM loan
    GROUP BY advance_id
    HAVING SUM(loan_amount) - SUM(deposit_amount) > 0;
    

    接下来,自行在advance table中进行必要的聚合,如下所示:

    SELECT advance_id, SUM(advance_amount) AS totalAdvance
    FROM advance
    GROUP BY advance_id;
    

    然后,我将加入这两个表以获得您需要的值:

    SELECT t1.advance_id, t1.totalAdvance, t2.totalLoan
    FROM(
      SELECT advance_id, SUM(advance_amount) AS totalAdvance
      FROM advance
      GROUP BY advance_id) t1
    JOIN(
      SELECT advance_id, SUM(loan_amount) AS totalLoan
      FROM loan
      GROUP BY advance_id
      HAVING SUM(loan_amount) - SUM(deposit_amount) > 0) t2 ON t2.advance_id = t1.advance_id;
    

    注意

    我没有包括目的或日期,因为它们在预付款表中不一致。您将不得不考虑每种情况。如果这两行的目的不同怎么办?日期不同,如果有的话,您需要返回哪个日期?一旦知道这一点,您就可以将它们添加到此查询中,可能是在“高级”子查询中。

    这是一个SQL Fiddle 示例。

    【讨论】:

      【解决方案2】:

      您想使用union all 而不是join 将这些表放在一起。或者,或者,在连接之前进行聚合。

      这里是union all 版本:

      SELECT advance_id,
             sum(advance_amount) as adv_amount,
             max(purpose) as purpose,
             min(date) as date,
             sum(loan_amount) as loan_amount
      FROM ((SELECT a.advance_id,
                    a.advance_amount,
                    a.purpose,
                    a.date,
                    NULL as loan_amount,
                    NULL as deposit_amount
             FROM advance
            ) UNION ALL
            (SELECT l.advance_id, NULL, NULL, l.date, loan_amount, deposit_amount
             FROM loan l
            )
           ) al
      GROUP BY advance_id
      HAVING sum(loan_amount) - sum(deposit_amount) > 0;
      

      【讨论】:

      • join前如何聚合?
      • 我想在这种情况下使用join
      猜你喜欢
      • 1970-01-01
      • 2015-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多