서브쿼리란?

반응형
728x90
반응형

서브쿼리란?

 1. 정의

 - 하나의 SQL문안에 포함되어 있는 또 다른 SQL문을 말한다.

 

 

 2. 주의점

 - 괄호로 감싸서 사용한다.

 - 단일 행(Single Row) 또는 복수 행(Multiple Row) 비교 연산자와 함께 사용 가능하다.

 - 단일 행 비교 연산자는 서브쿼리의 결과가 반드시 1건 이하이어야 하고, 복수 행 비교 연산자는 서브쿼리의 결과 건수와 상관 없다.

 - ORDER BY를 사용하지 못한다. ORDER BY절은 SELECT절에서 오직 한 개만 올 수 있기 때문에 ORDER BY절은

    메인쿼리의 마지막 문장에 위치해야 한다.

 

 

 3. 서브쿼리가 사용가능한 절

 -  SELECT 절, FROM 절, WHERE 절, HAVING 절, ORDER BY 절, INSERT문의 VALUES 절, UPDATE문의 SET 절

 

 

5. 단일행 서브쿼리

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

 

 

6. 단일행 서브쿼리 예제(1)

 SELECT PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버
  FROM PLAYER
 WHERE TEAM_ID =
     (SELECT TEAM_ID FROM PLAYER WHERE PLAYER_NAME = '정남일')
 ORDER BY PLAYER_NAME;

 

 

6. 단일행 서브쿼리 예제(2)

 SELECT PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버 
FROM PLAYER 
WHERE HEIGHT <= (SELECT AVG(HEIGHT) FROM PLAYER) 
ORDER BY PLAYER_NAME;

 

 

7. 다중행 서브쿼리

 

 

 

8. 다중 행 서브쿼리 예제

 

선수들 중에서 ‘정현수’라는 선수가 소속되어 있는 팀 정보를 출력 => error 

 

 SELECT REGION_NAME 연고지명, TEAM_NAME 팀명, E_TEAM_NAME 영문팀명 
FROM TEAM 
WHERE TEAM_ID = (SELECT TEAM_ID FROM PLAYER WHERE PLAYER_NAME = '정현수') 
ORDER BY TEAM_NAME

 -> ‘정현수’라는 이름을 가진사람이 1명 이상이기 때문에 에러.

 

 SELECT REGION_NAME 연고지명, TEAM_NAME 팀명, E_TEAM_NAME 영문팀명 
 FROM TEAM 
 WHERE TEAM_ID IN (SELECT TEAM_ID FROM PLAYER WHERE PLAYER_NAME = '정현수') 
 ORDER BY TEAM_NAME;

 -> IN 연산자를 통해 1명이상 조회 가능

 

 

 

9. 다중 컬럼 서브쿼리

 - 서브쿼리의 결과로 여러 개의 칼럼이 반환되어 메인쿼리의 조건과 동시에 비교되는 것을 의미한다.

  

소속팀별 키가 가장 작은 사람들의 정보를 출력

 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에서는 지원되지 않는 기능이다.

 

 

 

10. 연관 서브쿼리

 - 서브쿼리 내에 메인쿼리 칼럼이 사용된 서브쿼리이다.

  

선수 자신이 속한 팀의 평균 키보다 작은 선수들의 정보를 출력

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 선수명;

 -> EXISTS 서브쿼리의 특징은 아무리 조건을 만족하는 건이 여러 건이더라도 조건을 만족하는 1건만 찾으면 추가적인 검색을 진행하지 않는다.

 

 

 

11. FROM 절에서 서브쿼리 사용하기 = 인라인 뷰(Inline View)

 -  인라인 뷰는 SQL문이 실행될 때만 임시적으로 생성되는 동적인 뷰이기 때문에 데이터베이스에 해당 정보가 저장되지 않는다. 그래서 일반적인 뷰를 정적 뷰(Static View)라고 하고 인라인 뷰를 동적 뷰(Dynamic View)라고도 한다.

 

 

 

12. HAVING 절에서 서브쿼리 사용하기

 -  HAVING 절은 그룹함수와 함께 사용될 때 그룹핑된 결과에 대해 부가적인 조건을 주기 위해서 사용한다.

 

평균키가 삼성 블루윙즈팀의 평균키보다 작은 팀의 이름과 해당 팀의 평균키를 구하는 SQL

 

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')

 

 

 

13. UPDATE문에서의 SET절에서 사용하기

현재 TEAM 테이블에는 STADIUM_NAME 칼럼이 없다. TEAM 테이블에 STADIUM_NAME을 추가(ALTER TABLE ADD COLUMN)하였다고 가정하자. TEAM 테이블에 추가된 STADIUM_NAME의 값을 STADIUM 테이블을 이용하여 변경하고자 할 때 다음과 같이 SQL문을 작성할 수 있다.

  

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

  

 - 서브쿼리를 사용한 변경 작업을 할 때 서브쿼리의 결과가 NULL을 반환할 경우 해당 컬럼의 결과가 NULL이 될 수 있기 때문에 주의해야 한다.

 

 

 

14. INSERT문에서의 VALUES절에서 사용하기

PLAYER 테이블에 '홍길동'이라는 선수를 삽입하고자 한다. 이때 PLAYER_ID의 값을 현재 사용중인 PLAYER_ID에 1을 더한 값으로 넣고자 한다. 다음과 같이 SQL문을 SQL문을 작성할 수 있다.

 

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

 

 

 

 참고 교재 : SQL 전문가 가이드

참고 사이트 : http://bysql.net/

반응형

Designed by JB FACTORY