我的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美元。有谁知道这个陈述有什么问题?
答案 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。
表格布局和一些示例数据的描述会有所帮助。