❇️ 요약
- Subquery
- Scalar Subquery / Inline View
- Nested Subquery
- Single Row / Multiple Row / Multiple Column
📌 Subquery 사용시 주의
- Subquery는 괄호로 묶어서 사용
- 단일 행 또는 복수 행 비교 연산자와 함께 사용 가능
- Subquery에서 order by 사용 X
📌 Subquery 종류
스카라 서브쿼리(Scalar Subquery): SELECT 절에서 사용인라인 뷰(Inline View): FROM 절에서 사용중첩 서브쿼리(Nested Subquery): WHERE 절에서 사용
SELECT column1, (SELECT column2 FROM table2 WHERE condition)
FROM table1
WHERE condition;
SELECT case_number,
(SELECT avg(case_number)
FROM crime_status
WHERE crime_type = '강도'
AND status_type = '검거') avg
FROM crime_status
WHERE police_station = '은평'
AND crime_type = '강도'
AND status_type = '검거';
+-------------+--------+
| case_number | avg |
+-------------+--------+
| 1 | 4.1935 |
+-------------+--------+
1 row in set (0.01 sec)
SELECT a.column, b.column
FROM table1 a, (SELECT column1, column2 FROM table2) b
WHERE condition;
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;
+----------------+------------+-------------+
| police_station | crime_type | case_number |
+----------------+------------+-------------+
| 중부 | 폭력 | 997 |
| 종로 | 폭력 | 964 |
...
| 도봉 | 폭력 | 1234 |
| 수서 | 폭력 | 1394 |
+----------------+------------+-------------+
31 rows in set (0.00 sec)
Single Row:하나의 열을 검색하는 서브쿼리
Multiple Row:하나 이상의 열을 검색하는 서브쿼리
Multiple Column:하나 이상의 행을 검색하는 서브쿼리
한 개의 결과 값을 가져야 한다. (두개 이상인 경우 에러)SELECT column_names
FROM table_name
WHERE column_name = (SELECT column_name
FROM table_name
WHERE condition)
ORDER BY column_name;
SELECT name FROM celeb WHERE name = SELECT host FROM snl_show;
ERROR 1064 (42000): You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT host FROM snl_show' at line 1
SELECT name FROM celeb WHERE name = (SELECT host FROM snl_show);
ERROR 1242 (21000): Subquery returns more than 1 row
SELECT name FROM celeb WHERE name = (SELECT host FROM snl_show WHERE id = 1);
+-----------+
| name |
+-----------+
| 강동원 |
+-----------+
1 row in set (0.00 sec)
| 다중행 서브쿼리 연산자 | 설명 |
|---|---|
| IN | 서브쿼리 결과중에 포함 될 때 |
| EXISTS | 서브쿼리 결과에 값이 있으면 반환 |
| ANY | 서브쿼리 결과중에 최소한 하나라도 만족하면(비교연산자 사용) |
| ALL | 서브쿼리 결과를 모두 만족하면(비교 연산자 사용) |
IN
SELECT column_names
FROM table_name
WHERE column_name IN (SELECT column_name
FROM table_name
WHERE condition)
ORDER BY column_names;
EXISTS
SELECT column_names
FROM table_name
WHERE EXISTS (SELECT column_name
FROM table_name
WHERE condition)
ORDER BY column_names;
ANY
SELECT column_names
FROM table_name
WHERE column_name = ANY (SELECT column_name
FROM table_name
WHERE condition)
ORDER BY column_names;
ALL
SELECT column_names
FROM table_name
WHERE column_name = ALL (SELECT column_name
FROM table_name
WHERE condition)
ORDER BY column_names;
IN : SNL에 출연한 영화배우 조회
SELECT host
FROM snl_show
WHERE host IN (SELECT name
FROM celeb
WHERE job_title LIKE '%영화배우%');
+-----------+
| host |
+-----------+
| 강동원 |
| 차승원 |
+-----------+
2 rows in set (0.01 sec)
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);
+--------------------------+
| name |
+--------------------------+
| 서울강남경찰서 |
| 서울강서경찰서 |
| 서울관악경찰서 |
| 서울구로경찰서 |
| 서울노원경찰서 |
| 서울송파경찰서 |
| 서울영등포경찰서 |
| 서울중랑경찰서 |
+--------------------------+
8 rows in set (0.00 sec)
ANY : SNL에 출연한 적이 있는 연예인 이름 조회
SELECT name
FROM celeb
WHERE name = ANY (SELECT host
FROM snl_show);
+-----------+
| name |
+-----------+
| 강동원 |
| 유재석 |
| 차승원 |
| 이수현 |
+-----------+
4 rows in set (0.00 sec)
ALL : SNL에 출연한 적이 있고, snl_show의 ID가 1인 연예인 이름 조회
SELECT name
FROM celeb
WHERE name = ANY (SELECT host
FROM snl_show
WHERE id = 1);
+-----------+
| name |
+-----------+
| 강동원 |
+-----------+
1 row in set (0.00 sec)
SELECT column_names
FROM table_name a
WHERE (a.column1, a.column2, ...)
IN (SELECT b.column1, b.column2, ...
FROM table_name b
WHERE a.column_name = b.column_name)
ORDER BY column_names;
SELECT name, sex, agency
FROM celeb
WHERE (sex, agency) IN (SELECT sex, agency
FROM celeb
WHERE name = '강동원');
+-----------+------+----------------------+
| name | sex | agency |
+-----------+------+----------------------+
| 강동원 | M | YG엔터테이먼트 |
| 차승원 | M | YG엔터테이먼트 |
+-----------+------+----------------------+
2 rows in set (0.01 sec)