(1) Subquery
(2) 인라인 뷰(Inline View)
Subquery는 하나의 SQL 쿼리문 안에 포함되어 있는 또 다른 SQL 쿼리문을 말한다. 메인쿼리가 서브쿼리를 포함하는 종속적인 관계로 서브쿼리는 복잡한 데이터 검색이나 특정 조건에 맞는 데이터를 추출할 때 사용된다.
서브쿼리는 메인쿼리의 칼럼 사용이 가능하다. 서브쿼리는 메인쿼리 내의 쿼리에서 실행되며 메인쿼리의 칼럼을 참조하여 조건을 설정하거나 연산을 수행할 수 있다.
메인쿼리는 서브쿼리의 칼럼을 사용할 수 없다. 메인쿼리는 서브쿼리의 내부에서 정의된 칼럼이나 값을 직접 참조할 수 없다는 것이다.
Subquery 는 메인쿼리 내에서 괄호로 묶어서 사용해야 하며 단일 행 혹은 복수 행 비교 연산자와 함께 사용이 가능하다.
subquery에서는 값을 정렬하는 order by를 사용할 수 없다.
Subquery의 종류로는 Scalar Subquery, 인라인 뷰(Inline View), 중첩 서브쿼리 (Nested Subquery) 가 있다.
인라인 뷰(Inline View)는 SQL에서 사용하는 서브쿼리 종류 중 하나로, 서브쿼리를 FROM 절 안에 포함시켜 마치 테이블처럼 사용하는 것을 말한다. 인라인 뷰는 복잡한 쿼리를 단순화하거나 중간 결과를 처리하기 위해 사용되며 이를 통해 쿼리를 더욱 읽기 쉽고, 유지보수하기 쉬운 형태로 만드는 것이 가능하다. 즉 특정 작업을 수행하기 위해 sql 쿼리를 작성할 때 항상 작업을 쉽게 진행할 수 있고 쿼리를 공유하는 모든 팀원들이 읽기 쉽게 최상의 상태로 유지하기 위한 것이라고 할 수 있다.
FROM 절에 사용하는 서브쿼리, 메인쿼리에서는 인라인 뷰에서 조회한 열(Column) 만 사용가능하다.
# 경찰서 별로 가장 많이 발생한 범죄 건수와 범죄 유형을 조회
mysql> SELECT c.police_station, c.crime_type, c.case_number
FROM crime_status
(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;
인라인 뷰 서브쿼리 : 경찰서 별로 가장 많이 발생한 범죄 건수
#경찰서 별로 가장 많이 발생한 범죄 건수 (SELECT police_station, MAX(case_number) AS count FROM crime_status WHERE status_type LIKE '발생' GROUP BY police_station) m
SELECT police_station, MAX(case_number) AS count:crime_status테이블에서police_station별로case_number의 최대 값을 선택한다. 최댓값으로 구분하여 모은case_number열은AS count로 얼라이어스 하여count라는 별칭을 붙여준다.
FROM crime_status: 데이터를 조회할 테이블은crime_status이다.
WHERE status_type LIKE '발생':status_type이 '발생'인 행들만 선택한다.GROUP BY police_station: 각경찰서(police_station)별로 데이터를 그룹화하여최대 범죄 건수(case_number)를 찾는다.m: 인라인 뷰 서브쿼리로 각 경찰서에서 가장 많이 발생한 범죄 건수(case_number)를count라는 별칭으로 반환한 후group by하여 만든polcie_station을m이라는 이름의 임시 테이블로 사용한다.
메인쿼리 : 경찰서에서 가장 많이 발생한 범죄 건수와 해당 범죄 유형을 조회
#경찰서에서 가장 많이 발생한 범죄 건수와 해당 범죄 유형을 조회 mysql> SELECT c.police_station, c.crime_type, c.case_number FROM crime_status (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;
SELECT c.police_station, c.crime_type, c.case_number: 메인 쿼리에서는 최종적으로crime_status테이블에서police_station,crime_type,case_number열을 출력한다는 것이다.
FROM crime_status c: 데이터를 조회할 테이블crime_status를c라는 별칭으로 지정해준다.
WHERE c.police_station = m.police_station: 별칭을 붙여준 두 테이블c와m에서police_station이 동일한 행을 선택한다는 것이다.AND c.case_number = m.count: 별칭을 붙여준 두 테이블c의case_number가m의count와 동일한 행을 선택하여 결과를 추출하게 된다.
출력 결과
# 경찰서에서 가장 많이 발생한 범죄 건수와 해당 범죄 유형을 조회
mysql> 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 '검거';
+----------------+------------+------------+
| police_station | crime_type | case_number|
+----------------+------------+------------+
| 중부 | 폭력 | 997 |
| 종로 | 폭력 | 964 |
| 남대문 | 절도 | 699 |
| 서대문 | 폭력 | 1292 |
| 혜화 | 폭력 | 747 |
| 용산 | 폭력 | 1617 |
| 성북 | 폭력 | 672 |
| 동대문 | 폭력 | 1784 |
| 마포 | 폭력 | 1844 |
| 영등포 | 폭력 | 2701 |
| 성동 | 폭력 | 1223 |
| 동작 | 폭력 | 1631 |
| 광진 | 폭력 | 1676 |
| 서부 | 폭력 | 748 |
| 강북 | 폭력 | 1817 |
| 금천 | 폭력 | 1471 |
| 중랑 | 폭력 | 2022 |
| 강남 | 폭력 | 2283 |
| 관악 | 폭력 | 2614 |
| 강서 | 폭력 | 2445 |
| 강동 | 폭력 | 1942 |
| 종암 | 폭력 | 758 |
| 구로 | 폭력 | 2204 |
| 서초 | 폭력 | 1750 |
| 양천 | 폭력 | 1582 |
| 송파 | 폭력 | 2675 |
| 노원 | 폭력 | 2163 |
| 방배 | 폭력 | 423 |
| 은평 | 폭력 | 1092 |
| 도봉 | 폭력 | 1234 |
| 수서 | 폭력 | 1394 |
+----------------+------------+-------------+