Sql 聚合函数的分组列是否作为联接条件?

Sql 聚合函数的分组列是否作为联接条件?,sql,oracle11g,Sql,Oracle11g,我正在阅读一些Oracle SQL资源,发现以下SQL代码: SELECT e.ename AS "NAME", e.sal AS "Salary", e.deptno, AVG(a.sal) dept_avg FROM emp e, emp a WHERE e.deptno = a.deptno AND e.sal > ( SELECT AVG(sal) FROM emp

我正在阅读一些Oracle SQL资源,发现以下SQL代码:

 SELECT e.ename AS "NAME",
        e.sal AS "Salary", 
        e.deptno,
        AVG(a.sal) dept_avg
 FROM emp e, emp a
 WHERE e.deptno = a.deptno
 AND e.sal > ( SELECT AVG(sal) 
               FROM emp 
               WHERE deptno = e.deptno )
 GROUP BY e.ename, e.sal, e.deptno;
这个SQL代码应该返回每个获得超过其部门平均工资的员工,并显示其姓名、工资和部门ID,然后显示其部门的平均工资


为了返回dept_avg,我们必须按deptno进行分组,但是分组列很奇怪。我猜,分组列就是用作连接条件的列,即a.deptno。这是真的吗?如果没有,请有人澄清一下好吗?

也许用更现代的惯例重新书写会更清楚

WITH avgbydept as
(
   SELECT deptno, avg(sal) as avgsal
   FROM emp
   GROUP BY deptno
)
SELECT e.ename AS "NAME",
        e.sal AS "Salary", 
        e.deptno,
        AVG(a.sal) dept_avg
FROM emp e
JOIN emp a ON e.deptno = a.deptno
JOIN avgbydept abd ON e.deptno = abd.deptno
WHERE e.sal > abd.avgsal
GROUP BY e.ename, e.sal, e.deptno;
这说明了一件事,就是它有一个额外的连接和分组错误,按照你说的做:

此SQL代码应该返回每个获得超过 他所在部门的平均工资,并显示他的姓名,他的工资 他所在部门的ID,然后是他所在部门的平均工资

我相信你想要这个

WITH avgbydept as
(
   SELECT deptno, avg(sal) as avgsal
   FROM emp
   GROUP BY deptno
)
SELECT e.ename AS "NAME",
        e.sal AS "Salary", 
        e.deptno,
        abd.avgsal as dept_avg
FROM emp e
JOIN avgbydept abd ON e.deptno = abd.deptno
WHERE e.sal > abd.avgsal

也许用更现代的惯例重新书写会让它更清晰

WITH avgbydept as
(
   SELECT deptno, avg(sal) as avgsal
   FROM emp
   GROUP BY deptno
)
SELECT e.ename AS "NAME",
        e.sal AS "Salary", 
        e.deptno,
        AVG(a.sal) dept_avg
FROM emp e
JOIN emp a ON e.deptno = a.deptno
JOIN avgbydept abd ON e.deptno = abd.deptno
WHERE e.sal > abd.avgsal
GROUP BY e.ename, e.sal, e.deptno;
这说明了一件事,就是它有一个额外的连接和分组错误,按照你说的做:

此SQL代码应该返回每个获得超过 他所在部门的平均工资,并显示他的姓名,他的工资 他所在部门的ID,然后是他所在部门的平均工资

我相信你想要这个

WITH avgbydept as
(
   SELECT deptno, avg(sal) as avgsal
   FROM emp
   GROUP BY deptno
)
SELECT e.ename AS "NAME",
        e.sal AS "Salary", 
        e.deptno,
        abd.avgsal as dept_avg
FROM emp e
JOIN avgbydept abd ON e.deptno = abd.deptno
WHERE e.sal > abd.avgsal
分组可以让我们绕一圈。下面是一种简单的分组方式:

select field1, field1, sum(field3)
from ..
group by <all fields that do not participate in aggregate>
现在您可以看到别名为t的子查询将获得部门的平均工资。然后,我们使用部门将员工和导出的平均工资按部门合并,从而消除分组的需要。

GROUP by可以让我们陷入一个循环。下面是一种简单的分组方式:

select field1, field1, sum(field3)
from ..
group by <all fields that do not participate in aggregate>
现在您可以看到别名为t的子查询将获得部门的平均工资。然后,我们使用部门按部门加入员工和导出的平均工资,并消除分组的需要。

如果您删除GROUP by并使用SELECT*,您将看到发生了什么

emp本身就加入了,每个工资高于平均水平的员工都加入了其部门的所有其他员工,引起了极大的争吵。然后,根据这些数据,使用GROUP BY再次计算部门中其他所有员工的平均工资。它的效率低得令人印象深刻,看看其他答案,看看它应该是如何做到的。

如果您删除GROUP BY并使用SELECT*,您将看到发生了什么



emp本身就加入了,每个工资高于平均水平的员工都加入了其部门的所有其他员工,引起了极大的争吵。然后,根据这些数据,使用GROUP BY再次计算部门中其他所有员工的平均工资。它的效率低得令人印象深刻,看看其他答案,看看它应该是如何做到的。

这就是为什么使用旧样式的联接是愚蠢的。我不认为用内部联接重写这个查询会使它变得更好。@Timekiller为什么不呢?@Hogan旧样式对我来说就像新样式一样清晰,后者有时过于冗长,难以理解。也就是说,只要没有左/右连接,就不会涉及到那些可怕的+。我想这是一个品味的问题。@Timekiller-现实一点-你多久做一次有意义的工作而不必使用左连接。这就是为什么使用老式连接是愚蠢的。我不认为用内部连接重写这个查询会使它变得更好。@Timekiller为什么不呢?@Hogan旧的风格对我来说就像新的风格一样清晰,后者有时过于冗长,难以理解。也就是说,只要没有左/右连接,就不会涉及到那些可怕的+。我想这是一个品味的问题。@Timekiller-现实一点-你多久做一次重要的工作而不必使用左连接。如果这听起来很奇怪,请让我放松一点-我不是母语人士:3你的答案似乎接近我想要理解的!就像我们会得到这样的结果:加入后的第1行:name1,sal1,deptno1,sal1;join后的第二行:name1、sal1、deptno1、sal2等。。然后我们按姓名、工资和部门分组,得到sal1的平均值;sal 2。。。。谢谢:D@Hogan哦,好的,谢谢:3@MichaelHeidelberg删除分组方式并检查您聚合的内容在调试奇怪/错误的遗留查询时总是有很大帮助,我经常使用它。很乐意帮忙@Timekiller我认为你的回答做得很好。是的,他做到了,@Timekiller:信不信由你,我不能测试,因为我在Linux上,所以我不能尝试,因为我没有在那个系统上安装SQL server://如果听起来很奇怪,请放我一马——我不是以英语为母语的人:3你的答案似乎接近我想要理解的!就像我们会得到这样的结果:加入后的第1行:name1,sal1,deptno1,sal1;join后的第二行:name1、sal1、deptno1、sal2等。。然后我们按姓名、工资和部门进行分组,得出s的平均值
al1;sal 2。。。。谢谢:D@Hogan哦,好的,谢谢:3@MichaelHeidelberg删除分组方式并检查您聚合的内容在调试奇怪/错误的遗留查询时总是有很大帮助,我经常使用它。很乐意帮忙@Timekiller我认为你的回答做得很好。是的,他做到了,@Timekiller:信不信由你,我无法测试,因为我在Linux上,所以我无法尝试,因为我没有在该系统上安装SQL server://