2.2.4 서브쿼리

YJ·2022년 8월 30일
0

2.2.4 서브쿼리

  • 하나의 SQL문에 있는 또 다른 SQL문
  • 서브쿼리는 메인쿼리의 칼럼을 모두 사용할 수 있음
  • 메인쿼리는 서브쿼리의 칼럼을 사용할 수 없음
  • 서브쿼리는 항상 메인쿼리 레벨로 결과 집합이 생성
  • 서브쿼리에서는 ORDER BY 절을 사용하지 못하고, 메인쿼리 마지막 문장에 사용 가능
  • '서브쿼리가' SQL 문에서 사용 가능한 곳: SELECT 절, FROM 절, WHERE 절, HAVING 절, ORDER BY절, INSERT 문의 VALUES 절, UPDATE 문의 SET 절
  • 서브쿼리가 메인쿼리 칼럼을 가지고 있지 않은 경우: 비연관 서브쿼리, 가지는 경우: 연관 서브쿼리

단일 행 서브쿼리

  • 단일 행 비교연산자(=, <, >, <=, =>, <>)와 함께 사용할 때는 서브쿼리의 결과 건수가 반드시 1건 이하여야 함.

다중 행 서브쿼리

  • 결과가 2건 이상 반환될 수 있다면 반드시 다중 행 비교 연산자(IN, ALL, ANY, SOME)과 함께 사용

다중 칼럼 서브쿼리

  • 서브쿼리의 결과로 여러 개의 칼럼이 반환되어 메인쿼리의 조건과 동시에 비교되는 것
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE (TEAM_ID, HEIGHT) IN (SELECT TEAM_ID, MIN(HEIGHT)
                            FROM PLAYER
                            GROUP BY TEAM_ID)
ORDER BY TEAM_ID, PLAYER_NAME;
  • 같은 팀에서 여러 명이 반환됨. SQL Server에서는 지원되지않음

연관 서브쿼리

  • 서브쿼리 내에 메인쿼리 칼럼이 사용된 서브쿼리
SELECT T.TEAM_NAME 팀명, M.PLAYER_NAME 선수명, M.POSITION 포지션, M.BACK_NO 백넘버, M.HEIGHT 키
FROM PLAYER M, TEAM T
WHERE M.TEAM_ID = T.TEAM_ID
AND    M.HEIGHT < (SELECT AVG(S.HEIGHT)
                    FROM PLAYER S
                    WHERE S.TEAM_ID = M.TEAM_ID
                    AND S.HEIGHT IS NOT NULL
                    GROUP BY S.TEAM_ID)
ORDER BY 선수명;
  • EXIST 서브쿼리는 항상 연관 서브쿼리로 사용
  • 아무리 조건 만족하는 건이 여러 건이더라도 1건만 찾으면 추가적인 검색을 진행하지 않는다.
    (EXIST라 그런 듯)
SELECT STADIUM_ID ID, STADIUM_NAME 경기장명
FROM STADIUM A
WHERE EXISTS (SELECT 1
                FROM SCHEDULE X
                WHERE X.STADIUM_ID = A.STADIUM_ID
                AND X.SCHE_DATE BETWEEN '20120501' AND '20120502')

그 밖의 위치에서 사용하는 서브쿼리

SELECT 절에 서브쿼리 사용 - 스칼라 서브쿼리

  • 한 행, 한 컬럼만을 반환하는 서브퀄
  • 메인쿼리의 결과 건수만큼 반복수행됨

FROM 절에서 서브쿼리 사용 - 인라인 뷰

  • FROM 절에서 사용되는 서브쿼리: 인라인 뷰
  • 일반적인 뷰: 정적 뷰, 인라인 뷰와 같은 뷰: 동적 뷰 (SQL 문이 실행될 때만 임시적 생성)
  • 인라인 뷰의 칼럼은 SQL문에서 자유롭게 참조 가능함
  • ORDER BY 절 사용 가능함
SELECT T.TEAM_NAME 팀명, P.PLAYER_NAME 선수명, P.BACK_NO 백넘버
FROM (SELECT TEAM_ID, PLAYER_NAME, BACK_NO
		FROM PLAYERWHERE POSITION = 'MF') P,
        TEAM T
WHERE P.TEAM_ID = T.TEAM_ID
ORDER BY 선수명;

ORACLE

  • ROWNUM이라는 연산자 통해 => 정렬 결과로 추출하고자 하는 데이터의 건수 제한
SELECT PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM (SELECT PLAYER_NAME, POSITION, BACK_NO, HEIGHT
    FROM PLAYER
    WHERE HEIGHT IS NOT NULL
    ORDER BY HEIGHT DESC)
WHERE ROWNUM <=5;

SQL Server

  • TOP-N 쿼리를 통해 인라인 뷰에 먼저 정렬을 수행하고 정렬된 결과 중에서 일부 데이터를 추출
SELECT Top(5) PLAYER_NAME AS 선수명, POSITION AS 포지션, BACK_NO AS 백넘버, HEIGHT AS 키
FROM PLAYER
WHERE HEIGHT IS NOT NULL
ORDER BY HEIGHT DESC;

HAVING 절에서 서브쿼리 사용

SELECT P.TEAM_ID 팀코드, T.TEAM_NAME 팀명, AVG(P.HEIGHT) 평균키
FROM PLAYER P, TEAM T
WHERE P.TEAM_ID = T.TEAM_ID
GROUP BY P.TEAM_ID, T.TEAM_NAME
HAVING AVG(P.HEIGHT) < (SELECT AVG(HEIGHT)
                        FROM PLAYER
                        WHERE TEAM_ID = 'K02');

UPDATE 문의 SET 절에서 서브쿼리 사용

UPDATE TEAM A
SET A.E_TEAM_NAME = (SELECT X.STADIUM_NAME
                    FROM STADIUM X
                    WHERE X.STADIUM_ID = A.STADIUM_ID);

INSERT 문의 VALUES절에서 서브쿼리 사용

INSERT INTO PLAYER(PLAYER_ID, PLAYER_NAME, TEAM_ID)
VALUES((SELECT TO_CHAR(MAX(TO_NUMBER(PLAYER_ID))+1) FROM PLAYER),
	'홍길동', 'K06');

  • 실제 데이터를 가지고 있지 않다.
  • 가상 테이블이라고도 함.
CREATE VIEW V_PLAYER_TEAM AS
SELECT P.PLAYER_NAME, P.POSITION, P.BACK_NO, P.TEAM_ID, T.TEAM_NAME
FROM PLAYER P, TEAM T
WHERE P.TEAM_ID = T.TEAM_ID;
  • 이미 존재하는 뷰를 참조해서 또 뷰를 생성할수도 있다.
  • 뷰를 사용하기 위해 해당 뷰의 이름을 FROM 절에 적어 사용하면 됨
  • 제거: DROP VIEWS
profile
💻귀찮으니 필요할 때만 쓰는 Computer Vision 일지 ㅇㅇ💻

0개의 댓글