从联接的 table - returns 相乘结果中查询值的 SUM

Query SUM of value from joined table - returns multiplied result

在我的数据库中,我有 table:Job。每个作业都可以包含任务(一对多)——同一个任务可以在多个作业中重复使用。因此有一个 Task table 和一个 JobTask (连接点 table 用于多对多关系)。还有 Payment table,它记录收到的付款(使用 JobId 列来跟踪付款与哪个工作相关)。一项工作可能有不止一笔付款。

使用 SQL Server 2012,我有一个查询 returns 工作的简要摘要(工作的总价值,收到的总金额):

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

此查询的问题在于它为 "total received" 返回的金额比应有的金额高得多。一定是我遗漏了什么导致了这个。

在我的测试数据库中,我有一份工作。该作业分配有六个任务。它还分配了一笔付款(100 英镑 - 存储为 10000)。

对该数据使用上述查询,TotalReceivedP 列变为 60000,而不是 10000。它似乎乘以分配给该工作的每项任务的付款金额。瞧,如果我向该作业添加另一个任务(因此任务数现在为 7),TotalReceivedP 列显示 70000.

我的查询确实存在问题,但我无法弄清楚是什么问题。有没有敏锐的眼睛能看出来?连接似乎有问题。

使用 Sub-Select 计算 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

问题是您的 JOIN 约束不能足够具体,因此您得到的结果行太多。也许付款也应该加入任务?除非你 post 所有 table 模式,否则无法判断。

您应该将 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

对于每个单独的 JobIdSUM(p.Amount) 对与此 JobIdJob 记录相关的每个 Task 记录求和相同的金额值。如果 6 条记录与特定 Job 相关,则 SUM(p.Amount) 将计算金额乘以 6,如果 7 条记录相关,则金额乘以 7,依此类推。

因为每个 Job 只有一个 Payment 金额,所以不需要对 进行求和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 服务器,获取总和的一种非常简洁的方法(恕我直言)是 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

我只是在猜测 tables 架构,但以上内容应该可以满足您的需求。第一个 CTE 计算每个 JobId 的总和,第二个 CTE Amount 每个 JobId 的总和,最终查询使用两个 CTE 将结果放在一个 [=44] 中=].