서브쿼리(SubQuery)의 종류
서브쿼리의 종류는 크게 3종류로 분류할 수 있다.
- 단일행 서브쿼리 : 하나의 값만 리턴한다.
- 다중행 서브쿼리 : 여러 개의 행을 리턴한다.
- 다중행 열 서브쿼리 : 여러 개의 열로 구성된 여러 개의 행인 테이블을 리턴한다. (행,열이 다 있으므로 테이블 하나)
단일행 서브쿼리
서브쿼리는 SELECT문은 DB엔진에게 정보를 요구하는 명령이다. 단일행 서브쿼리는 WHERE절이나 HAVING절에 서브쿼리를 사용해서 더 세밀한 정보를 가져올 때 사용한다. 그러므로 스칼라 값(특정 값) 하나만 리턴한다.
사람에게 질문을 할 때 "너희 집은 어디야?" 이런 식의 간단한 질문도 하지만 너희 집의 구성원 수는 몇명이야?" 라는 질문식으로 "~의 " 로 들어가는 질문에 대한 결과를 원할 때 사용한다. 또한 집계함수 (COUNT(),MAX(),MIN(),SUM())을 WHERE절에 사용할 때도 사용한다. 왜냐하면 WHERE절에 단순히 집계함수를 쓰면 어떤 그룹에 대한 집계를 내려야하는 것을 의미하는지 DB엔진이 알 수 없기 때문에 서브쿼리를 사용한다.
단순한 질문
ex) 너희 집은 어디야?
SELECT home FROM tStudent WHERE name = '홍길동';
서브쿼리 사용 질문
ex) 너희 집의 구성원 수는 몇명이야? (너희 집을 먼저 찾고 가족구성원 수를 가지고 있는 tAddr에서 집 주소를 비교)
SELECT family_num FROM tAddr WHERE home = (SELECT home FROM tStudent WHERE name = '홍길동');
집계함수 사용 단일 행 서브쿼리
WHERE절에서 비교를 할 때 최대값, 최소값 등 집계함수를 사용해서 값을 비교를 할 때 단일행 서브쿼리를 사용한다.
왜냐하면 집계함수는 집계를 내기 위한 기준 그룹이 있어야하는데 FROM 절조차도 없으면 테이블 전체에 대한 그룹도 없기 때문에 서브쿼리가 필요하다.
ex) 사원 중 가장 봉급이 많이 버는 직원의 정보를 출력
SELECT * FROM tStaff WHERE salary = max(salary); => 얼핏보기에는 맞아보이지만 집계를 낼 수 있는 그룹이 없다.(x)
SELECT * FROM tStaff WHERE salary = (SELECT MAX(salary) FROM tStaff); => 서브쿼리를 통해서 집계를 낼 수 있는 그룹(tStaff 전체)를 가질 수 있어서 올바른 명령어(o)
서브쿼리의 중첩(테이블 2개 사용)
서브쿼리는 독립한 하나의 명령어이기 때문에 다른 테이블에서 읽어올 수 있다. "~의 " 형태의 더 자세한 질의에 사용된다.
서브쿼리 먼저 그리고 전체 쿼리가 순차적으로 실행되므로 다른 테이블이여도 상관이 없다.
청바지의 배송비가 얼마인지 조사해본다. 청바지는 상품 테이블(tItem)에 있지만 배송비는 유형 테이블(tCategory)을 읽어야한다.
step1)
SELECT category FROM tItem WHERE item = '청바지';
청바지의 유형을 검색한다. 결과는 '의류'이다
step2)
SELECT delivery FROM tCategory WHERE category = '의류')
'의류'를 통해서 배송비를 검색한다.
이 두가지 스텝은 하나로 줄이는 것이 서브쿼리의 중첩이다.
(one step)
SELECT delivery FROM tCategory WHERE category = (SELECT category FROM tItem WHERE item = '청바지');
익숙해지면 의식의 흐름을 따라서 한번에 작성할 수 있다. (청바지의 유형[의류]의 배송비는 무엇인가?) 테이블마다 연결되어 있는 FK는 인식하고 있어야 가능하다.
출처 : 김상혁의 SQL정복