SQL:加入表后 SUM() 函数返回错误值

Posted

技术标签:

【中文标题】SQL:加入表后 SUM() 函数返回错误值【英文标题】:SQL: After joining tables SUM() function returns wrong value 【发布时间】:2017-07-30 23:55:44 【问题描述】:

我目前正在处理一个数据库项目,并且在加入表时遇到了一些问题。初始情况是:

四个表:

任务 t ~ 50000 条记录 项目 p ~ 1000 条记录 workson w ~ 30000 条记录 员工 e ~ 10000 条记录

表 w 有一个类似“WORKLOAD”的属性,不幸的是 SUM(w.WORKLOAD) 的结果不是预期的:

SELECT
p.NAME,
SUM(w.WORKLOAD) AS "Total Workload",
COUNT(DISTINCT w.ESSN) AS "Total Employees",
COUNT(DISTINCT t.NAME) AS "Finished Tasks" --t.NAME is unique
from p 
JOIN w ON(p.PNUMBER = w.PNO)
JOIN t ON(p.PNUMBER = t.PNO)
WHERE t.END_DATE is NOT NULL
GROUP BY p.PNUMBER, p.NAME

加入这些表后,SUM() 函数返回一个太大的值。我猜这是因为 SUM() 函数多次计算每个 w.WORKLOAD 值。

那么有没有像内部连接这样的连接操作可以在不使用子查询的情况下解决问题? 提前致谢:-)

【问题讨论】:

每张表的表结构是什么? 解决方法是在join之前聚合。在您的情况下,您如何做到这一点尚不清楚。 如果显示 p.Name 的结果,为什么还要按 p.Number 分组? 表 p: pk=p.pnumber;表 w: pk=(e.ssn, p.pnumber);表 t:pk=(t.no, p.pnumber); 【参考方案1】:

问题是笛卡尔积(其中一个表中的行乘以其他表中的行)。以下方法所做的假设是每个项目都有一个分配了员工的工作负载(所有这些都考虑了所有员工,因为您的查询没有显示到员工表的连接)和任务。如果不是这种情况,请考虑使用外连接与内连接。

这个想法是根据项目编号在其自己的派生表中执行每个聚合。然后我们可以通过项目编号连接每个派生表以获得有意义的结果。

SELECT
p.NAME,
w.workload_sum AS "Total Workload",
e.employee_count AS "Total Employees",
t.task_count AS "Finished Tasks"
from p 
JOIN (select pno, sum(workload) as workload_sum
        from w
       group by pno) w ON (w.pno=p.pnumber)
JOIN (select pno, count(distinct w.essn) as employee_count
        from w
       group by pno) e ON (e.pno=p.pnumber)
JOIN (select pno, count(distinct t.name) as task_count
        from t
       group by pno) t ON (t.pno=p.pnumber)
WHERE t.END_DATE is NOT NULL;

【讨论】:

为什么你有两个 w 表的连接?您可以将 w 和 e 子查询合并为一个,如下所示:select pno, sum(workload) workload_sum, count(distinct essn) employee_count from w group by pno 它是一个占位符 - 按原样,员工可能不会被计算在内。该问题涉及员工表 - 这将是加入的正确表。

以上是关于SQL:加入表后 SUM() 函数返回错误值的主要内容,如果未能解决你的问题,请参考以下文章

SQL函数

sql函数

使用 SUM 函数时偶尔会出现转换错误

Sql Service的艺术 SQL聚合函数的应用

SQL 基础之组函数

SQL-SQL函数Aggregate 函数