在我的数据库中,我有表:Job
。每个作业都可以包含任务(一对多) - 并且可以在多个作业上重复使用相同的任务。因此,有一个Task
表和一个JobTask
(多对多关系的联结表)。还有Payment
表,用于记录收到的付款(使用JobId
列来跟踪付款与哪个作业相关)。可能会有多笔付款归因于某项工作。
使用SQL Server 2012,我有一个查询,返回作业的简短摘要(作业总值,收到的总金额):
select j.JobId,
sum(t.Rate) as [TotalOwedP],
sum(p.Amount) as [TotalReceivedP]
from Job j
left outer join Payment p on j.JobId=p.JobId
left outer join JobTask jt on j.JobId=jt.JobId
left outer join Task t on jt.TaskId=t.TaskId
group by j.JobId
此查询的问题在于它返回的“总收到”金额远高于应有的金额。我必须在这里找到一些可以引起这种情况的东西。
在我的测试数据库中,我有一份工作。这项工作分配了六个任务。它还分配了一笔付款(100英镑 - 存储为10000
)。
对此数据使用上述查询时,TotalReceivedP
列会显示60000
,而非10000
。它似乎是分配给工作的每项任务的支付金额倍增。请注意,如果我向此作业添加另一项任务(因此任务数量现为7),TotalReceivedP
列会显示70000
。
我的查询存在明确的问题,但我无法解决它的问题。任何敏锐的眼睛能够发现它吗?似乎连接有问题。
答案 0 :(得分:2)
使用子选择来计算SUM:
select j.JobId,
sum(t.Rate) as [TotalOwedP],
(SELECT SUM(p.Amount) FROM Payment p WHERE j.JobId=p.JobId) as [TotalReceivedP]
from Job j
left outer join JobTask jt on j.JobId=jt.JobId
left outer join Task t on jt.TaskId=t.TaskId
group by j.JobId
答案 1 :(得分:1)
对于每个单独的JobId
,SUM(p.Amount)
总结与Task
记录相关的每个Job
记录的相同金额值JobId
。如果6条记录与特定Job
相关,则SUM(p.Amount)
将计算金额乘以6,如果7条记录相关,则金额乘以7,依此类推。
由于每个作业只有一个付款金额,因此无需在 p.Amount
上执行总和。这样的话会给你想要的结果:
select j.JobId,
sum(t.Rate) as [TotalOwedP],
max(p.Amount) as [TotalReceivedP]
from #Job j
left outer join #Payment p on j.JobId=p.JobId
left outer join #JobTask jt on j.JobId=jt.JobId
left outer join #Task t on jt.TaskId=t.TaskId
group by j.JobId
修改强>
由于使用的平台是SQL Server,因此获得总和聚合的方式非常简洁(IMHO)CTEs
:
;WITH TaskGroup AS (
SELECT JobId, SUM(Rate) AS [TotalOwedP]
FROM #Task t
INNER JOIN #JobTask jt ON t.TaskId = jt.TaskId
GROUP BY JobId
), PaymentGroup AS (
SELECT JobId, SUM(Amount) [TotalReceivedP]
FROM #Payment
GROUP BY JobId
)
SELECT tg.JobId, tg.TotalOwedP, pg.TotalReceivedP
FROM TaskGroup tg
LEFT JOIN PaymentGroup pg ON tg.JobId = pg.JobId
我只猜测表架构,但上面应该给你你想要的东西。第一个CTE计算每Rate
个JobId
总和,每个Amount
的第二个CTE JobId
总和,最终查询使用两个CTE将结果放在一个表中。< / p>
答案 2 :(得分:0)
问题是你的JOIN约束必须不够具体,所以你得到的结果行太多了。可能还应该在Task上加入付款?除非你发布所有表格模式,否则无法判断。
答案 3 :(得分:0)
您应该将TotalOwed的查询与TotalReceived的查询分开。 TotalOwed基于各个任务,而付款则与作业相关联,而不是任务。
--first query
select j.JobId,
sum(t.Rate) as [TotalOwedP]
from Job j
left outer join JobTask jt on j.JobId=jt.JobId
left outer join Task t on jt.TaskId=t.TaskId
group by j.JobId
--second query
select j.JobId,
sum(p.Amount) as [TotalReceivedP]
from Job j
left outer join Payment p on j.JobId=p.JobId
group by j.JobId