在连接表上使用WHERE子句

时间:2016-11-30 15:48:38

标签: sql oracle

我正在尝试通过使用基于连接表的条件来找到过滤行的最佳方法。举个例子,我根据每个员工的工资等级加入员工和薪资等级表。然后我想只显示与某个员工(Blake)具有相同等级的员工。我使用了以下代码:

SELECT e.ename, e.sal, sg.grade  
FROM emp e JOIN salgrade sg  
ON(e.sal BETWEEN sg.losal AND sg.hisal)  
WHERE sg.grade = (SELECT sg.grade FROM emp e JOIN salgrade sg ON(e.sal BETWEEN sg.losal AND sg.hisal) WHERE e.ename = 'BLAKE')  
ORDER BY e.sal DESC

是否有更优化的方式来编写查询?

3 个答案:

答案 0 :(得分:0)

这是一种使用窗口函数的方法:

SELECT es.*
FROM (SELECT e.ename, e.sal, sg.grade,
             MAX(CASE WHEN e.ename = 'BLAKE' THEN sg.grade END) OVER () as blake_grade
      FROM emp e JOIN
           salgrade sg  
           ON e.sal BETWEEN sg.losal AND sg.hisal 
     ) es
WHERE grade = blake_grade 
ORDER BY e.sal DESC;

答案 1 :(得分:0)

我不会在WHERE子句中的select中使用连接;相反,我会使用内部标量子查询来获取BLAKE的工资,然后使用外部标量子查询来获取他的salgrade。否则与您的查询非常相似:

select e.ename, e.sal, s.grade
from   emp e inner join salgrade s on e.sal between s.losal and s.hisal
where  s.grade = ( select grade 
                   from   salgrade 
                   where  (select sal from emp where ename = 'BLAKE') 
                                                        between losal and hisal
                 )
order by sal desc
;

使用相同的想法,你也可以取消第一次加入(通过返回BLAKE的losalhisal以及他的salgrade),但也许这是太过分了。

答案 2 :(得分:0)

如果这只是不必两次编写相同的代码,您可以使用WITH子句:

WITH emps_and_sals AS
(
  SELECT e.ename, e.sal, sg.grade  
  FROM emp e 
  JOIN salgrade sg ON e.sal BETWEEN sg.losal AND sg.hisal
)
SELECT *
FROM emps_and_sals
WHERE grade = (SELECT grade FROM emps_and_sals WHERE ename = 'BLAKE')  
ORDER BY sal DESC;