期待结果不是来自mysql INNER JOIN

时间:2015-04-18 16:48:28

标签: mysql group-by inner-join having

我有以下两个表:

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

说明: 表'推进'是一个提前和表贷款的表格。是一个贷款账户表。为了相同的目的,可以多次使用预付款(此处购买产品)。每个进步都由预先ID标识。由于两个进步是出于同一目的(这里是购买产品),它们将具有相同的advance_id。另一方面,贷款是针对任何预付款。贷款也可以多次违反同样的进展。如果任何贷款将被偿还,它将被插入到deposit_amount列中以对抗advance_id。

在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.

2 个答案:

答案 0 :(得分:1)

loan_amount为double的原因是因为您使用advance_id在表之间进行内部联接。由于advance_id在advance_table中出现两次,因此贷款行将出现两次。在视觉上,联接给你这样的东西:

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

因此,当您在l.loan_amount上执行聚合时,它将被计算两次。为了解决这个问题,我会自己对每个表进行聚合,然后将它们连接在一起。例如,只需从贷款表中获取advance_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表中预先形成必要的聚合,如下所示:

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;

注意

我没有列出目的或日期,因为它们在高级表中不一致。你将不得不考虑每个案例。如果两行的目的不同怎么办?日期不同,如果有的话,您需要退回哪个日期?一旦你知道了,你可以将它们添加到这个查询中,可能是在&#39; advance&#39;子查询。

以下是SQL Fiddle示例。

答案 1 :(得分:0)

您希望使用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;