(MySQL) SQL 튜닝 용어 (2): 서브쿼리

최건우·2023년 8월 19일
0

데이터베이스/SQL

목록 보기
4/13

논리적인 SQL 개념 용어

SQL문 작성에 필요한 주변 오브젝트와 SQL 문의 상호관계, 연관성과 알고리즘에 관한 논리적 개념 용어를 학생 - 지도교수 테이블의 예제로 살펴보자.

학생 테이블

학번이름전공코드

지도교수 테이블

학번지도교수명

학생과 지도교수는 서로 일대일 관계이며, 지도교수 테이블의 학번 컬럼은 학생 테이블의 학번에 외래 키가 걸려있다고 가정하자.

1. 서브쿼리 위치에 따른 SQL 용어

서브쿼리(Subquery)쿼리 안의 보조 쿼리를 가리키는 용어이다. 가장 바깥쪽의 SELECT 문인 메인쿼리(main query)를 기준으로 내부에 SELECT 문을 추가해서 서브쿼리를 만든다. 이러한 서브쿼리는 작성하는 위치가 SELECT절, FROM절, WHERE절에 따라 부르는 용어가 달라진다.

SELECT   # Main query
	(SELECT ... FROM ...) ## Scalar subquery
FROM
	(SELECT ... FROM ...) ## Inline view
WHERE
	<column> IN (SELECT ... FROM ...) ## Nested subquery

스칼라 서브쿼리

스칼라 서브쿼리(Scalar subquery)란 메인쿼리의 SELECT 절에 있는 또다른 SELECT절을 의미한다.

메인쿼리의 SELECT 절에는 최종 출력하려는 열들이 나열되므로, 출력 데이터 1건과 스칼라 서브쿼리의 건수가 일치해야 한다. 즉, 스칼라 서브쿼리의 결괏값은 1행 1열의 구조로 추력되어야 한다.

보통 스칼라 서브쿼리는 출력되는 데이터 건수가 1건이어야 하므로, 집계함수(max, min, avg, sum, count 등)가 자주 쓰인다.

SELECT
	name,
	(SELECT COUNT(*)
    	FROM student AS student2
        WHERE student2.name = student1.name) AS COUNT
FROM
	student AS student1;

인라인 뷰

인라인 뷰(Inline view)란 FROM 절에 있는 또다른 SELECT 절이다. FROM 절 내부에서 일시적으로 뷰를 생성하는 방식이므로 인라인 뷰라고 불린다.
인라인 뷰의 결과는 내부적으로 메모리 또는 디스크에 임시 테이블을 생성하여 활용한다.

SELECT
	student2.number,
    student2.name
FROM
	(SELECT COUNT(*)
    	FROM student
        WHERE student.sex = 'male') AS student2;

중첩 서브쿼리

중첩 서브쿼리(nested subquery)란 메인쿼리의 WHERE 절에 있는 또 다른 SELECT 절을 가리킨다.
WHERE 절에서 단순한 값을 비교 연산하는 대신, 서브쿼리를 추가하여 비교 연산하기 위해 중첩 서브쿼리를 사용한다.

이처럼 WHERE 절에서 중첩 서브쿼리와 비교할 때는 보통 비교 연산자(=, <, >, <=, >=, <>, !=)를 비롯해 IN, EXISTS, NOT IN, NOT EXISTS 문을 만이 사용한다.

SELECT
	*
FROM
	students
WHERE
	students.number = (SELECT MAX(number) FROM student)

2. 메인쿼리와의 관계성에 따른 SQL 용어

서브쿼리는 메인쿼리의 관계에서 파생되는 용어들을 살펴보자. 서브쿼리는 그 자체가 독립적인 형태로 존재할 수도 있고, 메인쿼리와 깊은 관계를 유지하며 존재할 수도 있다.

비상관 서브쿼리

비상관 서브쿼리(non correlated subquery)는 메인쿼리와 서브쿼리 간에 관계성이 없음을 의미한다. 서브쿼리가 먼저 독자적으로 실행된 뒤 메인쿼리에게 그 결과를 던져주면, 메인쿼리가 그 결과를 활용하는 형태이다. 즉, 실행 순서가 서브쿼리 실행 -> 메인쿼리 실행의 순서로 실행된다.

아래 예제는 sex = 'male' 이라는 조건으로 student 테이블에서 데이터를 가져온 뒤, 그 결과를 메인쿼리의 학생 테이블로 전달하여 최종 데이터를 출력한다.

SELECT
	*
FROM
	student
WHERE
	number IN (SELECT
    				number
               FROM
               		student
               WHERE
               		sex = 'male')

상관 서브쿼리

상관 서브쿼리(correlated subquery)는 메인쿼리와 서브쿼리 간에 관계성이 있음을 의미한다. 서브쿼리가 수행되려면 메인쿼리의 값을 받아야 하는 관계에 있는 경우이다. 스칼라 서브쿼리, 중첩 서브쿼리에서 발생한다.

다음 예시에서는 지도교수(professor) 테이블에 대한 서브쿼리가 메인쿼리의 학생 학번(student.number)을 명시함으로써 그 관계를 뚜렷하게 보여준다.

SELECT
	*
FROM
	student
WHERE
	number IN (SELECT
    				number
               FROM
               		professor
               WHERE
               		professor.number = student.number)

전체적인 수행 순서는 메인 쿼리 실행(student.number 데이터 가져오기) -> 서브쿼리 실행(professor.number = student.number) -> 다시 메인쿼리 실행한 뒤 결과 출력(SELECT * FROM student ...) 와 같다. 메인쿼리에서 student.number 데이터를 전달받은 뒤 서브쿼리가 수행되고, 그 결과를 다시 메인쿼리로 전달한다.

3. 반환 결과에 따른 SQL 용어

서브쿼리의 결과 유형은 수치적 기준으로 구분할 수 있다.

  • 1건의 행 데이터만 반환하는 경우
  • 2건 이상의 행 데이터를 반환하는 경우
  • 2건 이상의 행과 열 데이터를 반환하는 경우

단일행 서브쿼리

단일행 서브쿼리(Single-row subquery)는 서브쿼리 결과가 1건의 행으로 반환되는 쿼리이다. 그에 따라 메인쿼리의 조건절에서는 =, <, > 등의 연산자와 비교한다. 단일행 서브쿼리는 스칼라 서브쿼리와 동일하다고 볼 수 있다.

다음 예제는 서브쿼리가 최댓값을 조회하므로, 항상 하나의 값만 반환된다.

SELECT
	...
FROM
	...
WHERE
	number = (SELECT MAX(number) FROM student)

다중행 서브쿼리

다중행 서브쿼리(Multiple-row subquery)는 서브쿼리 결과가 여러 건의 행으로 반환되는 쿼리이다. 그에 따라 메인쿼리의 조건절에서는 IN 구문으로 서브쿼리에서 반환되는 값들을 받는다.

다음 예제는 서브쿼리가 전공 코드이 종류만큼 학번의 최댓값을 조회하므로, 여러 건의 값이 반환된다.

SELECT
	...
FROM
	...
WHERE
	number IN (SELECT MAX(number) FROM student GROUP BY major_code)

다중열 서브쿼리

다중열 서브쿼리(Multiple-column subquery)는 서브쿼리 결과가 여러 개의 열과 행으로 반환된다. 그에 따라 메인쿼리의 조건절에서는 IN 구문으로 서브쿼리에서 반환될 열들을 동일하게 나열해 서브쿼리 결과를 받는다.

다음 예제는 학생 테이블에서 이름이 'KIM'으로 시작하는 학생의 이름과 전공코드를 반환하고, 메인쿼리에서는 반환되는 열들과 동일하게 WHERE(name, major_code) IN 구문으로 서브쿼리 결과를 받는다.

SELECT
	...
FROM
	...
WHERE
	(name, major_code) IN (SELECT name, major_code FROM student WHERE name LIKE 'KIM%')




profile
부족한 경험을 채우기 위한 나만의 기록 공간

0개의 댓글