3

考虑 Oracleemp表。我想用 和 得到薪水最高的department = 20员工job = clerk。还假设没有“empno”列,并且主键涉及许多列。你可以这样做:

select * from scott.emp
where deptno = 20 and job = 'CLERK'
and sal =  (select max(sal) from scott.emp
            where deptno = 20 and job = 'CLERK')

这可行,但我必须复制测试 deptno = 20 和 job = 'CLERK',这是我想避免的。有没有更优雅的方式来写这个,也许使用group by? 顺便说一句,如果这很重要,我正在使用 Oracle。

4

6 回答 6

3

以下是稍微过度设计的,但对于“top x”查询来说是一个很好的 SQL 模式。

SELECT 
 * 
FROM 
 scott.emp
WHERE 
 (deptno,job,sal) IN
 (SELECT 
   deptno,
   job,
   max(sal) 
  FROM 
   scott.emp
  WHERE 
   deptno = 20 
   and job = 'CLERK'
  GROUP BY 
   deptno,
   job
  )

另请注意,这将适用于 Oracle 和 Postgress(我认为),但不适用于 MS SQL。对于 MS SQL 中的类似内容,请参阅问题SQL Query to get latest price

于 2008-09-09T01:58:32.883 回答
2

如果我确定目标数据库,我会选择 Mark Nold 的解决方案,但如果您想要一些与方言无关的 SQL*,请尝试

SELECT * 
FROM scott.emp e
WHERE e.deptno = 20 
AND e.job = 'CLERK'
AND e.sal = (
  SELECT MAX(e2.sal) 
  FROM scott.emp e2
  WHERE e.deptno = e2.deptno 
  AND e.job = e2.job
)

*我相信这应该适用于任何地方,但我没有测试它的环境。

于 2008-09-09T08:00:40.893 回答
1

在 Oracle 中,我会使用分析函数来执行此操作,因此您只需查询一次 emp 表:

SELECT *
  FROM (SELECT e.*, MAX (sal) OVER () AS max_sal
          FROM scott.emp e
         WHERE deptno = 20 
           AND job = 'CLERK')
 WHERE sal = max_sal

它更简单、更容易阅读、更高效。

如果要修改它以列出所有部门的此信息,则需要在 OVER 中使用“PARTITION BY”子句:

SELECT *
  FROM (SELECT e.*, MAX (sal) OVER (PARTITION BY deptno) AS max_sal
          FROM scott.emp e
         WHERE job = 'CLERK')
 WHERE sal = max_sal
ORDER BY deptno
于 2008-09-15T14:04:05.790 回答
0

那太棒了!我不知道您可以将 (x, y, z) 与 SELECT 语句的结果进行比较。这适用于 Oracle。

作为其他读者的旁注,上述查询在“(deptno,job,sal)”之后缺少“=”。也许堆栈溢出格式化程序吃了它(?)。

再次感谢马克。

于 2008-09-09T03:24:11.430 回答
0

在 Oracle 中,您还可以使用 EXISTS 语句,这在某些情况下更快。

例如... SELECT name, number FROM cust WHERE cust IN (SELECT cust_id FROM big_table) 并输入 > SYSDATE -1 会很慢。

但是 SELECT name, number FROM cust c WHERE EXISTS ( SELECT cust_id FROM big_table WHERE cust_id=c.cust_id ) 并输入 > SYSDATE -1 会非常快,并且有适当的索引。您也可以将其与多个参数一起使用。

于 2008-09-09T11:51:12.977 回答
0

有很多解决方案。您还可以通过简单地添加表别名并加入列名来保留原始查询布局,但查询中仍然只有一次 DEPTNO = 20 和 JOB = 'CLERK'。

SELECT 
  * 
FROM 
  scott.emp emptbl
WHERE
  emptbl.DEPTNO = 20 
  AND emptbl.JOB = 'CLERK'
  AND emptbl.SAL =  
    (
      select 
        max(salmax.SAL) 
      from 
        scott.emp salmax
      where 
        salmax.DEPTNO = emptbl.DEPTNO
        AND salmax.JOB = emptbl.JOB
    )

还可以注意到,关键字“ALL”可用于这些类型的查询,这将允许您删除“MAX”功能。

SELECT 
  * 
FROM 
  scott.emp emptbl
WHERE
  emptbl.DEPTNO = 20 
  AND emptbl.JOB = 'CLERK'
  AND emptbl.SAL >= ALL  
    (
      select 
        salmax.SAL
      from 
        scott.emp salmax
      where 
        salmax.DEPTNO = emptbl.DEPTNO
        AND salmax.JOB = emptbl.JOB
    )

我希望这会有所帮助并且有意义。

于 2008-09-11T20:39:04.983 回答