在子查询中引用父查询
Referencing Parent query inside Child query
当子查询引用父查询时,任何人都可以解释这个查询。 SQL如何看待这个
员工的第二高薪水:
select max(e1.sal),e1.deptno
from s_emp e1
where sal < (select max(sal) from s_emp e2 where e2.deptno = e1.deptno)
group by e1.deptno;
我测试了它并且有效。
首先删除 group by 和聚合并考虑这个查询:
select e1.sal, e1.deptno
from s_emp e1
where e1.sal < (select max(sal) from s_emp e2 where e2.deptno = e1.deptno)
它 returns table 的所有行,除了 deptno
中最大 sal
的行。
为什么?
因为每一行的 sal
都与 deptno
的最高薪水进行比较,并且必须小于。
WHERE
子句中的子查询对 table:
的每一行执行一次
select max(e2.sal) from s_emp e2 where e2.deptno = e1.deptno
并且对于每一行,它 returns 当前行的最大值 sal
deptno
。
所以结果是所有小于当前行的 deptno
.
的最大值 sal
的 sal
现在,如果您添加 group by deptno
和聚合,您将获得每个 deptno
返回行的最大值 sal
,即 2nd 最高 sal
对于每个 deptno
,因为所有排名靠前的都已被排除。
这称为相关子查询,因为子查询的结果对于外部查询的每一行都可能不同。
当 MySQL 运行 是一个查询时,您可以将其视为对集合的 foreach 循环。例如在 PHP 语法中:
foreach (s_emp as e1) {
...
}
它 必须 运行 外部查询的每一行的子查询,然后才能评估 <
比较。随着行数的增加,这将变得非常昂贵。如果 table 有 N 行,它将 运行 子查询 N 次,即使 deptno! 只有几个不同的值也是如此。 MySQL 不够聪明,无法记住 运行 相同 deptno 值的子查询后的结果。
相反,您可以通过这种方式获得结果,它将计算所有 deptnos 的 max(sal),并将这些结果保存在临时 table。
select max(e1.sal), e1.deptno
from s_emp e1
join (select deptno, max(sal) as max_sal from s_emp group by deptno) as e2
on e1.deptno = e2.deptno
where e1.sal < e2.max_sal
group by e1.deptno
这个查询的目的似乎是 return 每个部门第二高的薪水,对吧?
这是另一个使用 MySQL 8.0 中的 window 函数的解决方案:
select deptno, sal
from (
select deptno, sal, dense_rank() over (partition by deptno order by sal desc) as dr
from s_emp
) as e1
where dr = 2
当子查询引用父查询时,任何人都可以解释这个查询。 SQL如何看待这个
员工的第二高薪水:
select max(e1.sal),e1.deptno
from s_emp e1
where sal < (select max(sal) from s_emp e2 where e2.deptno = e1.deptno)
group by e1.deptno;
我测试了它并且有效。
首先删除 group by 和聚合并考虑这个查询:
select e1.sal, e1.deptno
from s_emp e1
where e1.sal < (select max(sal) from s_emp e2 where e2.deptno = e1.deptno)
它 returns table 的所有行,除了 deptno
中最大 sal
的行。
为什么?
因为每一行的 sal
都与 deptno
的最高薪水进行比较,并且必须小于。
WHERE
子句中的子查询对 table:
select max(e2.sal) from s_emp e2 where e2.deptno = e1.deptno
并且对于每一行,它 returns 当前行的最大值 sal
deptno
。
所以结果是所有小于当前行的 deptno
.
的最大值 sal
的 sal
现在,如果您添加 group by deptno
和聚合,您将获得每个 deptno
返回行的最大值 sal
,即 2nd 最高 sal
对于每个 deptno
,因为所有排名靠前的都已被排除。
这称为相关子查询,因为子查询的结果对于外部查询的每一行都可能不同。
当 MySQL 运行 是一个查询时,您可以将其视为对集合的 foreach 循环。例如在 PHP 语法中:
foreach (s_emp as e1) {
...
}
它 必须 运行 外部查询的每一行的子查询,然后才能评估 <
比较。随着行数的增加,这将变得非常昂贵。如果 table 有 N 行,它将 运行 子查询 N 次,即使 deptno! 只有几个不同的值也是如此。 MySQL 不够聪明,无法记住 运行 相同 deptno 值的子查询后的结果。
相反,您可以通过这种方式获得结果,它将计算所有 deptnos 的 max(sal),并将这些结果保存在临时 table。
select max(e1.sal), e1.deptno
from s_emp e1
join (select deptno, max(sal) as max_sal from s_emp group by deptno) as e2
on e1.deptno = e2.deptno
where e1.sal < e2.max_sal
group by e1.deptno
这个查询的目的似乎是 return 每个部门第二高的薪水,对吧?
这是另一个使用 MySQL 8.0 中的 window 函数的解决方案:
select deptno, sal
from (
select deptno, sal, dense_rank() over (partition by deptno order by sal desc) as dr
from s_emp
) as e1
where dr = 2