문제
오라클을 고려해보세요 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을 사용하고 있습니다.
해결책
다음은 약간 과도하게 엔지니어링되었지만 "상위 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 쿼리
다른 팁
대상 데이터베이스가 확실하다면 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
)
*이 기능은 어디에서나 작동해야 한다고 생각하지만 테스트할 환경이 없습니다.
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
훌륭해요!(x, y, z)를 SELECT 문의 결과와 비교할 수 있는지 몰랐습니다.이는 Oracle과 잘 작동합니다.
다른 독자들을 위한 참고 사항으로, 위 쿼리에는 "(deptno,job,sal)" 뒤에 "="가 없습니다.어쩌면 스택 오버플로 포맷터가 그것을 먹었을 수도 있습니다(?).
다시 한 번, 마크에게 감사드립니다.
Oracle에서는 EXISTS 문을 사용할 수도 있는데, 경우에 따라 더 빠릅니다.
예를 들어...이름, cust in (big_table에서 cust_id를 select)에서 cust에서 번호를 선택하고 입력 한> sysdate -1은 느립니다.
그러나 Cust에서 이름, 번호를 선택하십시오 씨존재하는 곳 (big_table에서 cust_id를 선택하십시오 여기서 cust_id=c.cust_id ) 및 입력> sysdate -1은 적절한 인덱싱으로 매우 빠릅니다.여러 매개변수와 함께 사용할 수도 있습니다.
많은 솔루션이 있습니다.단순히 테이블 별칭을 추가하고 열 이름을 조인하여 원래 쿼리 레이아웃을 유지할 수도 있습니다. 쿼리에는 여전히 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
)
또한 "MAX" 기능을 제거할 수 있는 이러한 유형의 쿼리에 "ALL"이라는 키워드를 사용할 수 있다는 점도 참고할 수 있습니다.
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
)
도움이 되고 의미가 있기를 바랍니다.