考虑Oracle emp
表。我希望通过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。
答案 0 :(得分: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
答案 1 :(得分: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
)
*我相信这应该适用于所有地方,但我没有环境来测试它。
答案 2 :(得分: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
答案 3 :(得分:0)
太棒了!我不知道你可以将(x,y,z)与SELECT语句的结果进行比较。这适用于Oracle。
作为其他读者的旁注,上述查询在“(deptno,job,sal)”之后缺少“=”。也许Stack Overflow格式化器吃了它(?)。
再次感谢Mark。
答案 4 :(得分:0)
在Oracle中,您还可以使用EXISTS语句,在某些情况下更快。
例如...... SELECT名称,编号 来自cust 在哪里cust IN (SELECT cust_id FROM big_table) AND输入> SYSDATE -1 会很慢。
但 SELECT名称,编号 来自cust c 在哪里存在 (SELECT cust_id FROM big_table WHERE cust_id = c.cust_id ) AND输入> SYSDATE -1 通过适当的索引可以非常快。您也可以将它与多个参数一起使用。
答案 5 :(得分: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
)
我希望这有帮助并且有意义。