3 个表,左外连接,SUM

Posted

技术标签:

【中文标题】3 个表,左外连接,SUM【英文标题】:3 Tables, left outer join, SUM 【发布时间】:2009-02-05 21:07:05 【问题描述】:

我在 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 美元。有谁知道这个声明有什么问题?

【问题讨论】:

如果您提供一些示例数据和预期输出可能会有所帮助 我同意。目前尚不清楚为什么会有多个 VMP 记录。我认为您想要做的是将每个 acc_id 返回的 VMP 记录数减少到 1,但在没有一些示例 VMP 数据的情况下如何/最好的方法还不清楚。 【参考方案1】:

您应该知道,JOIN 会产生一组与连接子句匹配的所有组合。

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

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

【讨论】:

【参考方案2】:

由于您用于创建 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)

按 r.ret_desc、vmp.vlt_id 分组

第二,你为什么要做左连接? txn 绝对不是左连接,因为您在 wher 子句中使用了它,该子句有效地将其转换为内部连接,因此如果您需要将其作为左连接,则需要将 where 子句移至 on 子句。

【讨论】:

【参考方案3】:

我将对您的数据设计进行一些猜测。如果这些不准确,请更详细地更新问题。

(1) RET 表的主键为 ACC_ID (2) VMP 表以 (ACC_ID, VLT_ID) 作为其主键——所以当您说“有 50 条 VMP 记录”时,您的意思是 50 条具有相同 ACC_ID 但不同 VLT_ID 的记录。

基于这些假设,我猜您的问题是您没有将单个事务绑定到特定的 VLT_ID。

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

【讨论】:

以上是关于3 个表,左外连接,SUM的主要内容,如果未能解决你的问题,请参考以下文章

左外连接 - 如何在第二个表中返回一个布尔值?

Linq to Entity 具有多个左外连接

Linq 左外连接

netezza 左外连接查询性能

SQL - 范围之间的左外连接

SQL'左外连接与2个右表