Oracle sql查询 - 使用GROUP BY从另一个表获取SUM()

时间:2016-10-15 22:04:24

标签: sql oracle

有两个表:

员工表:

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从已付费表中获得的总数,这意味着如果我没有弄错,我需要使用SUMGROUP BY。但是,我只想选择lname和总数......

3 个答案:

答案 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
  • 这是做你想做的事情的标准方法。您也可以使用相关的子查询。
  • SELECTlname)中的未聚合列应该是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_idGROUP BY;另一种方法是修复他们的解决方案是单独选择MAX(lname) as lnameGROUP BY employee_id。我在SCOTT架构上做了这个,使用EMP和DEPT表,按部门汇总工资;几乎同样的问题。

优化器不会将一个解决方案转换为另一个解决方案 - 一个计划先组合然后加入,而另一个计划首先加入,然后加入组。优化器成本是相同的(对于非常小的输入表)但如果首先加入,则基数更大。

这是预期的:假设EMP有1000行,但只有4个部门。如果首先将一个组分组,则EMP表最多聚合为4行,这些行连接到DEPT。另一方面,如果我们首先加入,我们将加入1000行到4行 - 然后我们仍然将1000个结果行聚合到4,就像在另一个解决方案中一样。所以唯一的区别是联接的基数。

但是:我在HR模式上重复了相同的测试。在这种情况下,优化器确实将一个解决方案转换为另一个解决方案 - 它首先进行连接,然后才进行分组。这种情况的不同之处在于两个表中的department_id都有索引,优化器可以利用它(并更快地执行连接MUCH),但前提是它首先加入。如果它首先分组,则没有"索引"在生成的department_id列上。

所以:"它取决于" (和其他许多事情一样)。在任何情况下,如果有一个索引并且优化器认为最好先进行连接,它就会这样做。显然不是相反的方式。

相关问题