SQL Subquery
About Subquery
- 하나의 SQL 문안에 포함되어 있는 또 다른 SQL 문을 말한다.
- 메인쿼리가 서브쿼리를 포함하는 종속적인 관계이다.
- 서브쿼리는 메인쿼리의 칼럼 사용 가능
- 메인쿼리는 서브쿼리의 칼럼 사용 불가
Subquery 사용시 주의사항
- Subquery는 괄호로 묶어서 사용
- 단일 행 혹은 복수 행 비교 연산자와 함께 사용 가능
- Subquery 에서는 order by 를 사용x (정렬 불가)
Subquery 종류
- 스칼라 서브쿼리 (Scalar Subquery) - SELECT 절에 사용
- 인라인 뷰 (Inline View) - FROM 절에 사용
- 중첩 서브쿼리 (Nested Subquery) - WHERE 절에 사용
스칼라 서브쿼리 (Scalar Subquery)
- SELECT 절에서 사용하는 서브쿼리, 결과는 하나의 Column 이어야 한다
select column1, (select column2 from table2 where condition)
from table1
where condition;
스칼라 서브쿼리 (Scalar Subquery) 예제
- 서울은평경찰서의 강도 검거 건수와 서울시 경찰서 전체의 평균 강도 검거 건수를 조회
select case_number,
(select avg(case_number)
from crime_status
where crime_type like '강도' and status_type like '검거') avg
from crime_status
where police_station like '은평' and crime_type like '강도' and status_type like '검거';
![](https://velog.velcdn.com/images/dorong_park/post/b3df3ad1-d60d-440e-b62e-cf2024f7ce11/image.png)
인라인 뷰 (Inline View)
- FROM 절에 사용하는 서브쿼리, 메인쿼리에서는 인라인 뷰에서 조회한 Column 만 사용가능하다
select a.column, b.column
from table a, (select colmun1, colmun2 from table2) b
where condition;
인라인 뷰 (Inline View) 예제
- 경찰서 별로 가장 많이 발생한 범죄 건수와 범죄 유형을 조회
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 like '발생'
group by police_station) m
where c.police_station = m.police_station
and c.case_number = m.count;
![](https://velog.velcdn.com/images/dorong_park/post/8fcbc306-a5c2-437d-b3f4-11ba9790aba7/image.png)
중첩 서브쿼리 (Nested Subquery)
- WHERE 절에서 사용하는 서브쿼리
- Single Row - 하나의 열을 검색하는 서브쿼리
- Multiple Row - 하나 이상의 열을 검색하는 서브쿼리
- Multiple Column - 하나 이상의 행을 검색하는 서브쿼리
Single Row 문법
- 서브쿼리가 비교연산자(=, >, >=, <, <=, <>, !=)와 사용되는 경우, 서브쿼리의 검색 결과는 한개의 결과값을 가져와야 한다. (두개 이상인 경우 에러)
select column_names
from table_name
where column_names = (select column_name
from table_name
where condition)
order by column_name;
Single Row 예제
select name
from celeb
where name = (select host
from snl_show
where id = 1);
![](https://velog.velcdn.com/images/dorong_park/post/a3709054-0187-4c20-95bb-b37d69a68008/image.png)
Multiple Row - IN 문법
select column_names
from table_name
where column_names IN (select column_name
from table_name
where condition)
order by column_name;
Multiple Row - IN 예제
select host
from snl_show
where host in (select name
from celeb
where job_title like '%영화배우%');
![](https://velog.velcdn.com/images/dorong_park/post/7735c02f-58ad-4dd9-9521-496510456c94/image.png)
Multiple Row - EXISTS 문법
select column_names
from table_name
where exists (select column_name
from table_name
where condition)
order by column_names;
Multiple Row - EXISTS 예제
- 범죄 검서 혹은 발생 건수가 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);
![](https://velog.velcdn.com/images/dorong_park/post/e79bbb8a-93db-4586-ab55-256b2d47e6a8/image.png)
Multiple Row - ANY 문법
- 서브쿼리 결과 중에 최소한 하나라도 만족하면 (비교연산자 사용)
select column_names
from table_name
where column_name = ANY (select column_name
from table_name
where condition)
order by column_names;
Multiple Row - ANY 예제
- SNL 에 출연한 적이 있는 연예인 이름 조회
select name
from celeb
where name = ANY (select host
from snl_show);
![](https://velog.velcdn.com/images/dorong_park/post/aae8f20c-d100-4c87-9bf1-1eb8b8ed5426/image.png)
Multiple Row - ALL 문법
- 서브쿼리 결과 중에 모두 만족하면 (비교연산자 사용)
select column_names
from table_name
where column_name = ALL (select column_name
from table_name
where condition)
order by column_names;
Multiple Row - ALL 예제
select name
from celeb
where name = ALL (select host
from snl_show
where id = 1);
![](https://velog.velcdn.com/images/dorong_park/post/ca819678-27a0-4d99-bc90-6a2f98e2f776/image.png)
Multiple 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;
Multiple Column 예제
- 강동원과 성별, 소속사가 같은 연예인의 이름, 성별, 소속사를 조회
select name, sex, agency
from celeb
where (sex, agency) in (select sex, agency
from celeb
where name = '강동원');
![](https://velog.velcdn.com/images/dorong_park/post/b69dfba0-9130-4e2a-8aad-d8459341211d/image.png)