将不相关子查询重写为相关子查询

Posted

技术标签:

【中文标题】将不相关子查询重写为相关子查询【英文标题】:Rewriting uncorrelated subquery to correlated subquery 【发布时间】:2018-11-12 11:35:18 【问题描述】:

我正在使用带有附加表 PROJECT 的默认 oracle scott 数据库,其中有两列:projectnoempno

我想为每个项目选择薪水最高的员工。

我知道如何使用不相关的子查询来做到这一点:

SELECT p.projno, 
       e.sal, 
       e.ename
  FROM emp e 
 INNER 
  JOIN proj_emp p 
    ON e.empno = p.empno
 WHERE (e.sal, p.projno) 
    IN (SELECT MAX(e.sal), 
               p.projno 
          FROM emp e INNER JOIN proj_emp p 
            ON e.empno = p.empno
         GROUP BY p.projno)

但是,我被要求使用写在 WHERE 子句中的相关子查询来执行此操作,但我想知道这是否可能?

【问题讨论】:

您是否也被要求在没有窗口功能的情况下执行此操作? 在练习说明中,所有内容都是针对每个项目中薪水最高的员工的姓名,并在 WHERE caluse 中带有相关子查询 【参考方案1】:

我愿意:

SELECT t.*
FROM (SELECT p.projno, e.sal, e.ename,
             DENSE_RANK() OVER (PARTITION BY p.projno ORDER BY e.sal DESC) AS Seq
      FROM emp e INNER JOIN
           proj_emp p 
           ON e.empno = p.empno
     ) t
WHERE Seq = 1;

编辑:如果你想用相关子查询来做,那么我会重写你的查询以使 correlated

SELECT p.projno, e.sal, e.ename
FROM emp e INNER JOIN 
     proj_emp p 
     ON e.empno = p.empno
WHERE e.sal = (SELECT MAX(e1.sal)
               FROM emp e1 INNER JOIN 
                    proj_emp p1 
                    ON e1.empno = p1.empno
               WHERE p1.projno = p.projno
              );

【讨论】:

我忘了说,在练习指令中,据说在WHERE子句中写了相关子查询 我知道,但需要 correlated subquery。我用uncorrelated subquery 太棒了!这是我一直在寻找的解决方案!【参考方案2】:

使用窗口函数:

SELECT projno, sal, ename
FROM (SELECT p.projno, e.sal, e.ename,
             MAX(e.sal) OVER (PARTITION BY p.projno) as max_sal
      FROM emp e INNER JOIN
           proj_emp p 
           ON e.empno = p.empno
     ) ps
WHERE sal = max_sal;

【讨论】:

以上是关于将不相关子查询重写为相关子查询的主要内容,如果未能解决你的问题,请参考以下文章

在不使用相关子查询的情况下重写查询

SQL相关子查询与非相关子查询

重写查询以使用除 CTE 和子查询之外的窗口函数

相关子查询 和 不相关子查询

当SELECT后面的子查询不能被删除?

相关子查询 与非相关子查询