[SQL] : Subquery (2) / Subquery, 인라인 뷰(Inline View)

김대현·2024년 6월 14일

(1) Subquery
(2) 인라인 뷰(Inline View)

(1) Subquery

  • Subquery는 하나의 SQL 쿼리문 안에 포함되어 있는 또 다른 SQL 쿼리문을 말한다. 메인쿼리가 서브쿼리를 포함하는 종속적인 관계로 서브쿼리는 복잡한 데이터 검색이나 특정 조건에 맞는 데이터를 추출할 때 사용된다.

  • 서브쿼리는 메인쿼리의 칼럼 사용이 가능하다. 서브쿼리는 메인쿼리 내의 쿼리에서 실행되며 메인쿼리의 칼럼을 참조하여 조건을 설정하거나 연산을 수행할 수 있다.

  • 메인쿼리는 서브쿼리의 칼럼을 사용할 수 없다. 메인쿼리는 서브쿼리의 내부에서 정의된 칼럼이나 값을 직접 참조할 수 없다는 것이다.

  • Subquery 는 메인쿼리 내에서 괄호로 묶어서 사용해야 하며 단일 행 혹은 복수 행 비교 연산자와 함께 사용이 가능하다.

  • subquery에서는 값을 정렬하는 order by를 사용할 수 없다.

  • Subquery의 종류로는 Scalar Subquery, 인라인 뷰(Inline View), 중첩 서브쿼리 (Nested Subquery) 가 있다.



(2) 인라인 뷰(Inline View)

  • 인라인 뷰(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_stationm 이라는 이름의 임시 테이블로 사용한다.

메인쿼리 : 경찰서에서 가장 많이 발생한 범죄 건수와 해당 범죄 유형을 조회

#경찰서에서 가장 많이 발생한 범죄 건수와 해당 범죄 유형을 조회
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_statusc 라는 별칭으로 지정해준다.

  • WHERE c.police_station = m.police_station: 별칭을 붙여준 두 테이블 cm에서 police_station이 동일한 행을 선택한다는 것이다.
  • AND c.case_number = m.count : 별칭을 붙여준 두 테이블 ccase_numbermcount와 동일한 행을 선택하여 결과를 추출하게 된다.

출력 결과

# 경찰서에서 가장 많이 발생한 범죄 건수와 해당 범죄 유형을 조회
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        |
+----------------+------------+-------------+

profile
데이터 분석 스쿨 블로그 입니다.

0개의 댓글