1. 서브쿼리(SubQuery)
1) 하나의 SQL문 안에 포함되어 있는 또 다른 SQL문
2) 알려지지 않은 기준을 이용한 검색을 위해 사용
2. 메인쿼리의 질의 결과에 서브쿼리의 컬럼을 표시하기 위한 방법
- 서브쿼리는 메인쿼리의 컬럼을 모두 사용할 수 있지만 메인쿼리는 서브쿼리의 컬럼을 사용할 수 없음
1) JOIN 이용
2) 함수 이용
3) 스칼라 서브쿼리 이용
3. 서브쿼리 사용 시 주의사항
1) 서브쿼리를 괄호로 감싸서 사용해야 함
2) 서브쿼리는 단일 행(Single Row) 또는 복수 행(Multiple Row) 비교 연산자와 함께 사용 가능. 단일 행 비교 연산자는 서브쿼리의 결과가 반드시 1건 이하여야 하고 복수 행 비교 연산자는 서브쿼리의 결과 건수와 상관 없음.
3) 서브쿼리에서는 ORDER BY를 사용하지 못함. (ORDER BY절은 SELECT절에서 오직 한 개만 올 수 있기 때문)
4. 서브쿼리가 SQL문에서 사용이 가능한 곳
|
- SELECT 절 - FROM 절 - WHERE 절 - HAVING 절 - ORDER BY 절
- INSERT문의 VALUES 절 - UPDATE문의 SET 절 |
WHERE절
1) 동작하는 방식에 따른 서브쿼리 분류
| 종류 | 설명 |
| 비연관 서브쿼리 (Un-Correalated) |
- 서브쿼리가 메인쿼리 컬럼을 가지고 있지 않은 형태의 서브쿼리 - 메인쿼리에 값(서브쿼리가 실행된 결과)를 제공하기 위한 목적으로 주로 사용 |
| 연관 서브쿼리 (Correalated) |
- 서브쿼리가 메인쿼리 컬럼을 가지고 있는 형태의 서브쿼리 - 일반적으로 메인쿼리가 먼저 수행되어 읽혀진 데이터를 서브쿼리에서 조건이 맞는지 확인하고자 할 때 주로 사용 |
| [연관 서브쿼리 예제]
선수 자신이 속한 팀의 평균 키보다 작은 선수들의 정보를 출력하는 SQL문을 연관 서브쿼리를 이용해서 작성
|
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 선수명;
2) 반환되는 데이터의 형태에 따른 서브쿼리 분류
| 종류 | 설명 |
| 단일 행 서브쿼리 (Single Row) |
- 서브쿼리의 실행 결과가 항상 1건 이하인 서브쿼리(2건 이상 반환 시 런타임 에러 발생) - 단일 행 비교 연산자 <, <=, =, >, >=, <> 와 함께 사용함 |
| 다중 행 서브쿼리 (Multi Row) |
- 서브쿼리의 실행 결과가 여러 건인 서브 쿼리 - 다중 행 비교 연산자 IN, ALL, ANY, SOME, EXISTS와 사용함 |
| 다중 컬럼 서브쿼리 (Multi Column) |
- 서브쿼리의 실행 결과로 여러 컬럼 반환 - 메인쿼리의 조건절에 여러 컬럼 동시 비교 가능(비교하고자하는 컬럼 개수와 컬럼 위치가 동일해야함) - SQL Server에서는 지원되지 않음 |
- 다중 행 비교 연산자
| 종류 | 설명 |
| IN | 서브쿼리의 결과에 존재하는 임의의 값과 동일한 조건 의미(Multiple OR 조건) |
| 비교연산자 ALL | 서브쿼리의 결과에 존재하는 모든 값을 만족하는 조건 의미 ex) 비교 연산자로 ">"를 사용했다면, 서브쿼리 결과의 최대값보다 큰 모든 건이 조건을 만족 |
| 비교연산자 ANY/SOME | 서브쿼리의 결과에 존재하는 어느 하나의 값이라도 만족하는 조건 의미 ex) 비교 연산자로 ">"를 사용했다면, 서브쿼리 결과의 최소값보다 큰 모든 건이 조건 만족 |
| EXISTS | - 서브쿼리의 결과를 만족하는 값이 존재하는지 여부를 확인하는 조건 의미 - 조건을 만족하는 건이 여러 건이라도 1건만 찾으면 더이상 검색하지 않음 - EXISTS 서브쿼리는 항상 연관 서브쿼리로 사용됨 |
| [다중 행 비교연산자 IN 예제]
선수들 중에서 ‘정현수’라는 선수가 소속되어 있는 팀 정보를 출력하는 서브쿼리 작성
|
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;
| [다중 행 비교연산자 EXISTS 예제]
EXISTS 서브쿼리를 사용하여 '20120501' 부터 '20120502' 사이에 경기가 있는 경기장 조회
|
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')
| [다중 컬럼 서브쿼리 예제] 소속팀별 키가 가장 작은 사람들의 정보를 출력 GROUP BY를 이용하여 SQL문 작성할 것 |
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;
서브쿼리의 결과값으로 소속팀코드(TEAM_ID)와 소속팀별 가 장 작은 키를 의미하는 MIN(HEIGHT)라는 두 개의 컬럼을 반환
메인쿼리에서는 조건 절에 TEAM_ID와 HEIGHT 칼럼을 괄호로 묶어서 서브쿼리 결과와 비교하여 원하는 결과를 얻음
SELECT절
SELECT 절에서 사용하는 서브쿼리인 스칼라 서브쿼리(Scalar Subquery)
- 한 행, 한 칼럼(1 Row 1 Column)만을 반환하는 서브쿼리를 말함 => 단일행 서브쿼리
- 스칼라 서브쿼리는 칼럼을 쓸 수 있는 대부분의 곳에서 사용할 수 있음
FROM 절
FROM 절에서 사용되는 서브쿼리를 인라인 뷰(Inline View) 또는 동적 뷰(Dynamic View)라고 함
- 서브쿼리의 결과가 마치 실행 시에 동적으로 생성된 테이블인 것처럼 사용할 수 있음
- SQL문이 실행될 때만 임시적으로 생성되는 동적인 뷰이기 때문에 데이터베이스에 해당 정보가 저장되지 않음
- 인라인 뷰 를 사용하는 것은 조인 방식을 사용하는 것과 같음, 그렇기 때문에 인라인 뷰의 칼럼은 SQL문 자유롭게 참조 가능
- 인라인 뷰에서는 ORDER BY절을 사용할 수 있다. 인라인 뷰에 먼저 정렬을 수행하고 정 렬된 결과 중에서 일부 데이터를 추출하는 것을 TOP-N 쿼리라고 한다. TOP-N 쿼리를 수행하기 위해서는 정렬 작업과 정렬 결과 중에서 일부 데이터만을 추출할 수 있는 방법이 필요하다. Oracle에서는 ROWNUM이라는 연산자를 통해서 결과로 추출하고자 하는 데이터 건수를 제약할 수 있다.
| [예제]
K-리그 선수들 중에서 포지션이 미드필더(MF)인 선수들의 소속팀명 및 선수 정보를 출력
|
SELECT T.TEAM_NAME 팀명, P.PLAYER_NAME 선수명, P.BACK_NO 백넘버
FROM (SELECT TEAM_ID, PLAYER_NAME, BACK_NO
FROM PLAYER
WHERE POSITION = 'MF') P, TEAM T
WHERE P.TEAM_ID = T.TEAM_ID
ORDER BY 선수명;
| [예제]
인라인 뷰에서 선수의 키를 내림차순으로 정렬(가장 키가 큰 선수부터 출력) 한 후 메인쿼리에서 ROWNUM을 사용해서 5명의 선수의 정보만을 추출
|
Oracle
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
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 절
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')
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);
INSERT문의 VALUES절에서 사용하기
| [예제]
PLAYER 테이블에 '홍길동'이라는 선수를 삽입하고자 한다. 이때 PLAYER_ID의 값을 현재 사용중인 PLAYER_ID에 1을 더한 값으로 넣고자 할 때 SQL문 작성
|
INSERT INTO PLAYER(PLAYER_ID, PLAYER_NAME, TEAM_ID)
VALUES((SELECT TO_CHAR(MAX(TO_NUMBER(PLAYER_ID))+1)
FROM PLAYER), '홍길동', 'K06');
'DB' 카테고리의 다른 글
| [DB] 마리아 디비(MariaDB) 사용해보기 (0) | 2023.11.02 |
|---|---|
| [SQL] 뷰(View) (0) | 2023.03.13 |
| [SQL] CASE 표현 (1) | 2023.03.06 |
| [SQL] NULL 관련 함수 (0) | 2023.03.06 |
| [SQL] 테이블 삭제, 테이블의 데이터 삭제 drop, truncate, delete비교 (0) | 2023.03.05 |