문제

오라클을 고려해보세요 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
    )

도움이 되고 의미가 있기를 바랍니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top