3个表,左外连接,SUM

时间:2009-02-05 21:07:05

标签: sql

我的3个表上的LEFT OUTER JOIN出现问题,带有SUM子句。 这是我的代码:

SELECT r.ret_desc, vmp.vlt_id,  
SUM((vmp.cash_in + vmp.per_cash_in_sec)
  + (CASE WHEN vmp.acc_id = t.db_id AND t.txn_type_id = 1 THEN t.amount ELSE 0 END)
  - (CASE WHEN vmp.acc_id = t.cr_id AND t.txn_type_id = 1 THEN t.amount ELSE 0 END)) AS in_adj, 

FROM ret AS r
LEFT OUTER JOIN vmp ON r.acc_id = vmp.acc_id
LEFT OUTER JOIN txn AS t ON (r.acc_id = t.credit_acc_id OR r.acc_id = t.debit_acc_id) 

WHERE t.txn_type_id IN (1,2,4,5)
GROUP BY r.ret_desc, vmp.vlt_id
;

问题是存在多个VMP记录,并且SUM字段乘以VMP记录的COUNT。例如:如果SUM字段应该等于100美元并且有50个VMP记录,则SUM变为5000美元,而它应该是100美元。有谁知道这个陈述有什么问题?

3 个答案:

答案 0 :(得分:1)

您应该知道JOIN会生成一组与join子句匹配的所有组合。

因此,如果单个ret记录有多个txn和vmp记录,则每个ret得到count(txn)* count(vmp)记录,从而创建count(vmp)* txn.amount和count的总和( txn)* vmp.amount。

我认为最好的解决方案是使用2个子选择进行外连接,或者在vmp和txn上创建视图,对每个ret进行分组和求和,然后将它们连接起来。

答案 1 :(得分:1)

由于您用于创建sunm的所有字段都来自可能存在多个记录的表,当然它们都会添加它们。

你正在做的事情有几个问题,但首先如果我是你,我会把这笔钱拿出来看看你的总结之前的计算是什么。事实上,我会做类似的事情:

SELECT r.ret_desc, vmp.vlt_id,  
(vmp.cash_in + vmp.per_cash_in_sec)  
 + (CASE WHEN vmp.acc_id = t.db_id AND t.txn_type_id = 1 THEN t.amount ELSE 0 END) 
 - (CASE WHEN vmp.acc_id = t.cr_id AND t.txn_type_id = 1 THEN t.amount ELSE 0 END),
vmp.cash_in,vmp.per_cash_in_sec, vmp.per_cash_in_sec,  t.db_id,t.cr_id,         t.txn_type_id ,t.amount
FROM ret AS r
LEFT OUTER JOIN vmp ON r.acc_id = vmp.acc_id
LEFT OUTER JOIN txn AS t ON (r.acc_id = t.credit_acc_id OR r.acc_id = t.debit_acc_id) 
WHERE t.txn_type_id IN (1,2,4,5)

GROUP BY r.ret_desc,vmp.vlt_id

你为什么要做左连接? txn绝对不是左连接因为你在wher子句中使用它有效地将其转换为内连接,所以如果你需要它是一个左连接,你需要将where子句移动到on子句。

答案 2 :(得分:0)

我将对您的数据设计做出一些猜测。如果问题不准确,请更新问题。

(1)RET表以ACC_ID为主键   (2)VMP表具有(ACC_ID,VLT_ID)作为其主键 - 因此当您说“有50个VMP记录”时,您指的是具有相同ACC_ID但不同VLT_ID的50个记录。

根据这些假设,我猜你的问题是你没有将个别交易绑定到特定的VLT_ID。

表格布局和一些示例数据的描述会有所帮助。