有两个表:
员工表:
employee_id, lname
E01 | Smith
E02 | Johnson
E03 | Williams
E04 | Jones
薪资表:
employee_id, paid
E01 | 199
E04 | 751
E01 | 599
E02 | 299
E03 | 259
E03 | 357
E02 | 671
E04 | 130
如何仅查询员工的姓氏,以及他们的总薪水?我的尝试吸引了太多行:
SELECT lname, total_paid
FROM Employee
CROSS JOIN (SELECT SUM(paid) AS total_paid FROM Salary GROUP BY employee_id);
我的问题是,我需要select
从已付费表中获得的总数,这意味着如果我没有弄错,我需要使用SUM
和GROUP BY
。但是,我只想选择lname和总数......
答案 0 :(得分:0)
您可以使用此query
代替您的。只需在employee_id列上的Salary表上进行左连接。
SELECT Employee.lname, SUM(Salary.paid) as total_paid FROM Employee
LEFT JOIN Salary on Employee.employee_id=Salary.employee_id
GROUP BY Employee.employee_id
答案 1 :(得分:0)
您需要加入表格,然后汇总:
SELECT e.lname, SUM(s.paid) as total_paid
FROM Employee e JOIN
Salary s
ON e.employee_id = s.employee_id
GROUP BY e.lname;
注意:
LEFT JOIN
。SELECT
(lname
)中的未聚合列应该是GROUP BY
中的列。答案 2 :(得分:0)
Gordon和Mww的解决方案的替代方案是首先聚合,然后进行连接。 (在运行查询之前,Oracle优化器可能会将其中一个解决方案转换为另一个解决方案 - 我发现这是一个有趣的问题,我将进行实验和报告)。这也非常接近你所尝试的 - CROSS加入是错误的。您需要将employee_id
保留在子查询中,然后加入employee_id
。
编辑:实际上,Gordon和mww提供的答案是不正确的。两者都按员工姓氏分组,忽略了可能有不同员工姓氏相同的事实。所以我的测试看看Oracle优化器做了什么"没有实际意义;查询不等同。 结束修改
另一点是,对于在薪资表中没有任何相应行的员工,左连接将使total_paid保留为NULL。如果您需要将其设置为0(零),则可以使用CASE
表达式或其等效表达式NVL()
。
select e.lname, nvl(g.total_paid, 0) as total_paid
from employee e left join ( select employee_id, sum(paid) as total_paid
from salary
group by employee_id
) g
on e.employee_id = g.employee_id;
测试结果
我将我的解决方案与Gordon's和mww's进行了比较(假设它们已更正为lname
中包含employee_id
和GROUP BY
;另一种方法是修复他们的解决方案是单独选择MAX(lname) as lname
和GROUP BY employee_id
。我在SCOTT架构上做了这个,使用EMP和DEPT表,按部门汇总工资;几乎同样的问题。
优化器不会将一个解决方案转换为另一个解决方案 - 一个计划先组合然后加入,而另一个计划首先加入,然后加入组。优化器成本是相同的(对于非常小的输入表)但如果首先加入,则基数更大。
这是预期的:假设EMP有1000行,但只有4个部门。如果首先将一个组分组,则EMP表最多聚合为4行,这些行连接到DEPT。另一方面,如果我们首先加入,我们将加入1000行到4行 - 然后我们仍然将1000个结果行聚合到4,就像在另一个解决方案中一样。所以唯一的区别是联接的基数。
但是:我在HR模式上重复了相同的测试。在这种情况下,优化器确实将一个解决方案转换为另一个解决方案 - 它首先进行连接,然后才进行分组。这种情况的不同之处在于两个表中的department_id都有索引,优化器可以利用它(并更快地执行连接MUCH),但前提是它首先加入。如果它首先分组,则没有"索引"在生成的department_id
列上。
所以:"它取决于" (和其他许多事情一样)。在任何情况下,如果有一个索引并且优化器认为最好先进行连接,它就会这样做。显然不是相反的方式。