4.1 서브쿼리
서브쿼리(Subquery) : SQL문은 하나의 결과를 반환하는 독립적인 사용자 함수와 같은 기능을 한다. 따라서 함수가 들어갈 수 있는 위치에는 그에 맞는 결과를 반환하는 별도의 SQL문을 삽입할 수 있으며, 이를 서브쿼리라고 한다. 서브쿼리를 품고 있는 쿼리를 상대적인 표현으로 메인쿼리라고 한다. 서브쿼리는 반드시 괄호로 감싸서 사용해야 하며, 삽입되는 위치에 따라 다음과 같이 분류할 수 있다.
종류 | 삽입되는 위치 |
---|---|
스칼라 서브쿼리 | SELECT문의 칼럼 입력 위치 |
인라인 뷰 | FROM절의 테이블 입력 위치 |
중첩 서브쿼리 | WHERE절, HAVING절의 칼럼 또는 테이블 입력 위치 |
또한 메인쿼리의 칼럼 사용 여부에 따라 다음과 같이 분류할 수 있다.
종류 | 메인쿼리 칼럼 사용 여부 |
---|---|
연관 서브쿼리 | 메인쿼리의 칼럼을 서브쿼리에서 사용 |
비연관 서브쿼리 | 메인쿼리의 칼럼을 서브쿼리에서 비사용 |
스칼라 서브쿼리 : SELECT문의 칼럼이 입력되는 위치(SELECT, ORDER BY 등)에 들어가는 서브쿼리.
SELECT A.NAME,
(SELECT B.NUM
FROM TEST2 B) AS NUM
FROM TEST1 A;
인라인 뷰(INline View) : FROM절의 테이블이 입력되는 위치에 들어가는 서브쿼리. 쿼리 실행 시 생성되는 동적 테이블로 볼 수 있다.
SELECT A.NAME
FROM (SELECT NAME
FROM TEST) AS A;
뷰(View) : 서브쿼리의 반환 결과로 생성된 테이블에 별도로 이름을 붙여서 DBMS에 등록해 놓고 테이블을 참조하듯이 사용할 수 있도록 한 것. 해당 뷰를 참조할 때 동적으로 메모리에 생성되는 임시/가상 테이블이다.
테이블 | 뷰 | |
---|---|---|
개념 | 정의된 스키마에 따라 실제 데이터를 물리적으로 생성. |
실제 테이블을 참조하여 생성하는 논리적인 가상 테이블. |
데이터 저장 | 실제 데이터를 디스크에 저장. | 실제 데이터를 저장하지 않음. |
생성 방식 | 정적으로 생성. | 동적으로 생성. |
인덱스 생성 | 고유 인덱스 생성 가능. | 고유 인덱스 생성 불가능. |
삽입/수정/삭제 | 제약 없음. | 제약 있음. |
특징 | 설명 |
---|---|
편리성 | 복잡하고 긴 쿼리를 단순하게 작성할 수 있다. |
보안성 | 기존 테이블에서 특정 칼럼을 제외시키고 뷰를 생성하여 제공할 수 있다. |
독립성 | 테이블의 구조가 변경되더라도 뷰를 통한 접근은 변경할 필요가 없다. |
CREATE OR REPLACE VIEW V_TEST AS
[ SELECT 등의 쿼리문 ];
=> V_TEST 뷰를 생성한다.
SELECT * FROM V_TEST;
=> V_TEST 뷰의 모든 칼럼을 조회한다. (테이블처럼 사용할 수 있다.)
DROP VIEW V_TEST;
=> V_TEST 뷰를 삭제한다.
중첩 서브쿼리 : 쿼리 안에 다른 쿼리가 중첩되어 들어간 경우, 특히 WHERE절과 HAVING절에 들어가는 서브쿼리. 스칼라 서브쿼리, 인라인 뷰와 다르게 여러 형태의 반환값을 가질 수 있다.
반환값 유형 | 설명 |
---|---|
단일행 | 반환되는 값이 단일행인 경우. 단일행 비교연산자의 연산 대상으로 지정할 수 있다. |
다중행 | 반환되는 값이 다중행인 경우. 다중행 비교연산자의 연산 대상으로 지정할 수 있다. |
다중칼럼 | 반환되는 값이 여러 칼럼(벡터), 즉 테이블인 경우. |
① 단일행 :
SELECT NAME,
SCORE
FROM STUDENT
WHERE SCORE >= (SELECT AVG(S.SCORE) FROM STUDENT S);
=> 학점이 평균 이상인 학생을 조회.
② 다중행 :
SELECT NAME,
SCORE,
MAJOR
FROM STUDENT
WHERE MAJOR IN (SELECT DISTINCT MAJOR
FROM STUDENT
WHERE SCORE <= 2.7);
=> 학점이 2.7이하인 학생이 있는 전공의 학생들을 조회.
③ 다중칼럼 :
SELECT NAME,
SCORE,
MAJOR
FROM STUDENT
WHERE (SCORE, MAJOR) IN (SELECT MAX(SCORE), MAJOR
FROM STUDENT
GROUP BY MAJOR);
=> 전공별로 가장 학점이 높은 학생을 조회.