Subquery
란?
메인 query
라고 하며, 이 안에 포함되어 있는 SQL문을 subquery
라고 한다.Scalar Subquery(스칼라 서브쿼리)
: SELECT 절에 사용Inline View(인라인 뷰)
: FROM 절에 사용Nested Subquery(중첩 서브쿼리)
: WHERE 절에 사용Scalar Subquery(스칼라 서브쿼리)
는 SELECT 절에서 사용하는 subquery로 결과는 하나의 column 이어야 한다.
Scalar Subquery 문법
SELECT column1, (SELECT column2 FROM table2 WHERE condition) FROM table1 WHERE condition;
Example: 서울은평경찰서의 강도 검거 건수와 서울시 경찰서 전체의 평균 강도 검거 건수를 조회하기
1) 서울은평경찰서의 강도 검거 건수를 조회하기
select case_number
from crime_status
where police_station like '은평' and crime_type='강도' and status_type='검거';
2) 서울시 경찰서 전체의 평균 강도 검거 건수를 조회하기 (subquery)
select avg(case_number)
from crime_status
where crime_type='강도' and status_type='검거';
3) 서울은평경찰서의 강도 검거 건수와 서울시 경찰서 전체의 평균 강도 검거 건수를 조회하기
select case_number,
(select avg(case_number)
from crime_status
where crime_type='강도' and status_type='검거') avg
from crime_status
where police_station like '은평' and crime_type='강도' and status_type='검거';
Inline View(인라인 뷰)
는 FROM 절에 사용하는 subquery로, 메인 query에서는 인라인 뷰에서 조회한 column만 사용 가능하다.
Inline View 문법
SELECT a.column, b.column FROM table1 a, (SELECT column1, column2 FROM table2) b WHERE condition;
Example: 경찰서 별로 가장 많이 발생한 범죄 건수의 범죄 유형을 조회하기
1) 경찰서 별로 가장 많이 발생한 범죄 건수 조회하기 (subquery)
select police_station, max(case_number) count
from crime_status
where status_type='발생'
group by police_station; #경찰서 별
2) 경찰서 별로 가장 많이 발생한 범죄 건수의 범죄 유형을 조회하기
select c.police_station, c.crime_type, c.case_number
from crime_status c,
(select police_station, max(case_number) count
from crime_status
where status_type='발생'
group by police_station) m
where c.police_station = m.police_station
and c.case_number = m.count;
Nested Subquery(중첩 서브쿼리)
는 WHERE 절에서 사용하는 subquery로,
Single Row
: 하나의 행(row)을 검색하는 subqueryMultiple Row
: 하나 이상의 행(row)을 검색하는 subqueryMultiple Column
: 하나 이상의 열(column)을 검색하는 subquerySingble row subquery
는 subquery가 비교 연산자(Comparison Operators)(=, >, >=, <=, <, <>, !=)와 사용하는 경우, subquery의 검색 결과는 한 개의 결과값을 가져야 한다.
하지만, 결과값이 두개 이상인 경우, 에러가 발생한다.
Single Row Subquery 문법_
SELECT column_names FROM table_name WHERE column_name = (SELECT column_name FROM table_name WHERE condition) ORDER BY column_name;
Example 1: celeb 테이블에서 snl_show 테이블의 host와 같은 데이터 찾기 (괄호( ) X)
select name from celeb
where name = select host from snl_show;
이렇게 괄호( )를 쓰면 에러가 발생하는 걸 확인할 수 있다.
select name from celeb
where name = (select host from snl_show);
위와 같은 query 또한 비교 연산자를 사용함으로 snl_show 테이블에서 한개 이상의 host 결과값을 불러오기에 에러가 발생한다.
Example 2: celeb 테이블에서 snl_show 테이블 중 host의 ID가 1인 데이터 찾기
select name from celeb
where name = (select host from snl_show where id = 1);
Multiple Row - IN 문법
Subquery 결과 중에 포함(IN) 될때
SELECT column_names FROM table_name WHERE column_name IN (SELECT column_name FROM table_name WHERE condition) ORDER BY column_names;
Example: snl_show에 출연한 영화배우를 조회하기
select host
from snl_show
where host in (select name
from celeb
where job_title like '%영화배우%');
위의 문제는 Multiple Row (IN)의 예시로써 IN을 썼지만 JOIN을 쓰는게 더 효율적이다.
Multiple Row - EXISTS 문법
Subquery 결과에 값이 있으면 반환
SELECT column_names FROM table_name WHERE EXISTS (SELECT column_name FROM table_name WHERE condition) ORDER BY column_names;
Example: 범죄 검거 혹은 발생 건수가 2000건 보다 큰 경찰서 조회하기
select police_station, reference
from crime_status
where case_number > 2000;
select name
from police_station p
where exists (select police_station
from crime_status c
where p.name = c.reference and case_number > 2000);
Multiple Row - ANY 문법
Subquery 결과 중에 최소한 하나라도 만족하면 (비교 연산자 사용)
SELECT column_names FROM table_name WHERE column_name = ANY (SELECT column_name FROM table_name WHERE condition) ORDER BY column_names;
Example: snl_show에 출연한 적이 있는 연예인 이름 조회하기
select name
from celeb
where name = any (select host
from snl_show);
아래처럼 써도 위의 결과값과 똑같다.
select name
from celeb c, snl_show s
where c.name = s.host;
Multiple Row - ALL 문법
Subquery 결과를 모두 만족하면 (비교 연산자 사용)
SELECT column_names FROM table_name WHERE column_name = ALL (SELECT column_name FROM table_name WHERE condition) ORDER BY column_names;
Example: snl_show의 ID가 1인 host와 동일한 이름을 가진 celeb의 이름 찾기
select name
from celeb
where name = all (select host
from snl_show
where id = 1);
Multiple Column 문법
subquery 내에 메인 query 열(column)이 같이 사용되는 경우
SELECT column_names FROM tablename a WHERE (a.column1, a.column2, ...) IN (SELECT b.column1, b.column2, ... FROM tablename b WHERE a.column_name = b.column_name) ORDER BY column_names;
Example: 강동원과 성별, 소속사가 같은 연예인의 이름, 성별, 소속사를 조회하기
select name, sex, agency
from celeb
where (sex, agency) IN (select sex, agency
from celeb
where name = '강동원');