본문 바로가기
MYSQL

SUBQUERY

by 융디's 2024. 5. 7.
728x90
SUBQUERY

SUBQUERY

@2024.05.03

SUBQUERY

💡
하나의 SQL 질의문 속에 다른 SQL 질의문이 포함되어 있는 형태

Single-Row SUBQUERY

💡
SubQuery의 결과가 한 행(ROW) 경우 사용
  • =, >, >=, <, <=, <> 연산자 사용
  • 예시
    1. 이름으로 정렬했을 때 첫 번째 나오는 이름의 이름, 급여, 부서 번호 출력하라.
    SELECT ename, sal, deptno
    FROM emp
    WHERE ename = (SELECT MIN(ename) FROM emp);
    1. 사원의 평균 급여보다 작은 급여를 받는 사원의 이름과 급여를 출력하라.
    SELECT ename, sal
    FROM emp
    WHERE sal < (SELECT AVG(sal) From emp);
    1. 부서 이름이 SALES인 부서의 사원 이름과 부서 번호를 출력하라.
    SELECT ename, deptno
    FROM emp
    WHERE deptno = (SELECT ename FROM emp WHERE dname = 'SALSE');

Multi-Row SUBQUERY

💡
SubQuery의 결과가 두 행(ROW) 이상인 경우 사용
  • ANY, ALL, IN, EXIST 등 연산자 사용
    • 부서별 이름 순서가 첫 번째 사원 이름, 급여, 부서 번호를 출력하라.
    -- 잘못된 문장
    SELECT ename, sal, deptno 
    FROM emp
    WHERE ename = (SELECT MIN(ename) FROM emp GROUP BY deptno);
    • 부서별로 최소 ename 값을 갖는 사원이 여러 명 존재할 가능성이 있다!
    • 따라서 서브 쿼리가 여러 행을 반환하므로, = 연산자와 비교할 수 없다!
    -- 위에 잘못된 문장의 올바른 예
    SELECT ename, sal, deptno
    FROM emp
    WHERE ename IN (SELECT MIN(deptno) FROM emp GROUP BY deptno); 
  • IN
    • 다수의 비교 값 중 하나라도 만족하면 True
    • 모든 조건에 OR 연산을 수행한 것과 동일
    -- sal == 950 or 3000 or 1250 
    SELECT * FROM emp Where sal IN(950, 3000, 1250); 
  • ANY
    • 다수의 비교 값 중 하나라도 만족하면 True
    • 모든 조건에 OR 연산을 수행한 것과 동일
    • IN과 다른 점은 비교 연산자를 사용할 수 있다는 점
      • 만약 =을 사용할 때 서브 쿼리의 여러 개라면 오류 발생
    -- 950보다 큰 값을 모두 출력하라 
    SELECT * FROM emp Where sal > ANY(950, 3000, 1250); 
  • ALL
    • 전체 값을 비교하여 모두 만족하면 True
    • 모든 조건에 AND 연산을 수행한 것과 동일
    -- 모두 다 같을수는 없기에 False 
    SELECT * FROM emp Where sal = ALL(950, 3000, 1250);  
    -- 3000보다 큰 값만 출력 
    SELECT * FROM emp Where sal > ALL(950, 3000, 1250); 

Correlated Query

💡
메인 쿼리의 결과에 따라 서브 쿼리가 실행되는 서브 쿼리 형태로 상호 연관 서브 쿼리라고도 불린다.
  • Outer Query와 Inner Query가 서로 연관되어 있다.
  • 실행 과정
    1. Outer Query의 한 행을 얻는다.
    1. 해당 행을 가지고 Inner Query를 계산
    1. 계산 결과를 이용하여 Outer Query의 WHERE 절을 평가
    1. 결과가 참이면 해당 행을 결과에 포함시킨다.
  • 예시
    1. 사원의 이름, 급여, 부서 번호를 출력하라.
      단, 사원의 급여가 그 사원이 속한 부서의 평균 급여보다 큰 경우에만 출력하라.
    SELECT A.ename, A.sal, A.deptno
    FROM emp A
    WHERE A.sal > (SELECT AVG(B.sal) FROM emp B WHERE A.deptno = B.deptno); 
    1. 각 부서별로 최고 급여를 받는 사원을 출력하라.
    -- 방법 1 
    SELECT deptno, empno, ename, sal
    FROM emp
    WhERE (deptno, sal) IN (SELECT deptno, MAX(sal) FROM emp Group BY deptno);
    
    -- 방법 2
    SELECT A.deptno, A.empno, A.ename, A.sal
    /* 서브 쿼리 : emp 테이블을 사용하여 각 부서의 최고 급여을 계산 - C라는 별칭 사용 */
    FROM emp A, (SELECT B.deptno, MAX(B.sal) AS msal FROM emp B GROUP BY deptno) C
    /* 부서 번호와 급여가 서브쿼리에서 계산된 최고 급여와 일치하는 행만 선택 */
    WHERE A.deptno = C.deptno AND A.sal = C.msal;

Set Operator

💡
set 연산자는 두 개 이상의 쿼리 결과를 결합하는 데 사용

UNION (A ∪ B)

💡
두 개의 쿼리 결과를 결합하고, 중복된 행을 제거
SELECT * FROM A UNION SELECT * FROM B;

UNION ALL (A ∪ B)

💡
두 개의 쿼리 결과를 결합하나, 중복된 행을 제거하지 않는다.
SELECT * FROM A UNION ALL SELECT * FROM B;

INTERSECT (A ∩ B)

💡
두 개의 쿼리 결과에서 공통된 행만을 선택하며 해당 키워드는 MySQL에서 지원하지 않는다.
SELECT A.name FROM A, B WHERE A.name = B.name;

MINUS(=EXCEPT)(A - B)

💡
첫 번째 쿼리 결과에서 두 번째 쿼리 결과에 없는 행 선택하며, 해당 키워드는 MySQL에서 지원하지 않는다.
SELECT A.name FROM A WHERE A.name not in (SELECT B.name FROM B);

RANK() 함수

💡
MYSQL 8.0버전부터 도입된 함수로, 주어진 집합 내에서 특정 값의 순위를 지정하는 함수다.
  • 예시
    • 직원의 급여와 이름을 선택하고, 급여를 기준으로 내림차순으로 정렬된 순서대로 각 직원의 순위를 지정
    SELECT sal, ename, RANK() OVER(ORDER BY sal DESC) AS ranking
    FROM emp;

    < 쿼리 실행 전 >

    empnoenamesal
    1001Alice5000
    1002Bob4000
    1003Charlie4500
    1004David5500

    < 쿼리 실행 후 >

    salenameranking
    5500David1
    5000Alice2
    4500Charlie3
    4000Bob4

728x90

'MYSQL' 카테고리의 다른 글

CREATE / INSERT 절  (0) 2024.05.30
MYSQL 명령어 총 정리  (0) 2024.05.26
조인  (0) 2024.05.07
GROUP BY  (0) 2024.05.05
형 변환  (0) 2024.05.05