[데이터 베이스] Subquery
Subquery
서브쿼리는 SQL구문 내에 포함된 또 다른 SQL 쿼리로 메인 쿼리의 일부로 중첩 되어 실행되어 메인 쿼리에 데이터를 제공한다.
서브쿼리는 메인 쿼리의 SELECT, FROM, WHERE, HAVING 등 다양한 위치에서 사용될 수 있다.
서브쿼리를 사용하면 조건에 따라 동적으로 데이터를 필터링하거나, 계산된 값을 메인 쿼리로 전달하여 복잡한 데이터 요구사항을 효율적으로 해결할 수 있다.
- 단일 행 서브쿼리
SELECT employee_id, name, salary
FROM employees
WHERE salary > (
SELECT AVG(salary)
FROM employees
);
결과로 단일 행을 반환하여 메인 쿼리의 조건과 비교될 때 사용된다.
위의 쿼리는 평균 급여보다 더 많은 급여를 받는 직원을 출력한다.
- 다중 행 서브쿼리
SELECT employee_id, name, department_id
FROM employees
WHERE department_id IN (
SELECT department_id
FROM departments
WHERE location_id = '1000'
);
결과로 여러 행을 반환하며, IN, ANY, ALL, EXISTS 등의 연산자와 함께 사용될 수 있다.
위의 쿼리는 부서의 위치 번호가 1000인 것에 해당하는 부서번호의 직원을 출력한다.
IN
IN 연산자는 서브쿼리의 결과 집합 내에 메인 쿼리의 열값이 존재하는지 확인하고 값이 결과 집합에 속하면 TRUE를 반환한다.
SELECT * FROM employees
WHERE department_id IN (SELECT id FROM departments WHERE name = 'Sales');
ANY / SOME
ANY와 SOME은 서브쿼리가 반환하는 값 중에서 하나라도 조건을 만족하면 TRUE를 반환한다.
ANY와 SOME은 동일하게 작동하며, 비교 연산자(=, <>, >, <, >=, <=)와 함께 사용된다.
SELECT * FROM employees
WHERE salary > ANY (SELECT salary FROM employees WHERE department_id = 2);
ALL
ALL 연산자는 서브쿼리의 모든 값이 주어진 비교 조건을 만족할 때 TRUE를 반환한다.
ALL은 주로 비교 연산자(>, <)와 같은 조건을 표현할 때 사용된다.
SELECT * FROM employees
WHERE salary > ALL (SELECT salary FROM employees WHERE department_id = 3);
EXISTS
EXISTS 연산자는 서브쿼리가 최소한 하나 이상의 행을 반환하는지 여부를 확인한다.
이때 반환하는 결과가 있다면 TRUE를 반환하고 그렇지 않으면 FALSE를 반환한다.
EXISTS는 주로 상호 연관 서브쿼리에서 사용되어 메인 쿼리의 행이 서브쿼리 조건과 일치하는지를 검사한다.
SELECT * FROM employees e
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.employee_id = e.id);
단일 값 비교
단일 값 비교 연산자(=, <>, >, <, >=, <=)는 서브쿼리가 단 하나의 값을 반환할 때 사용된다.
이러한 연산자는 서브쿼리의 결과와 메인 쿼리의 열값을 직접 비교한다.
SELECT * FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);
- 상호 연관 서브쿼리
SELECT e.employee_id, e.name, e.salary
FROM employees e
WHERE e.salary > (
SELECT AVG(salary)
FROM employees
WHERE department_id = e.department_id
);
메인 쿼리의 열을 참조하여 실행이 되기 때문에 subquery만 따로 실행하면 오류가 발생한다.
위의 쿼리는 자신의 부서의 평균보다 급여를 많이 받는 직원을 출력한다.
JOIN 과의 차이점
JOIN과 서브쿼리는 모두 SQL에서 데이터를 결합하거나 관련 데이터를 조회하는 데 사용되는 두 가지 방법이다.
따라서 JOIN과 서브쿼리를 사용해서 동일한 결과를 얻을 수도 있다.
하지만 상황에 따라서 JOIN을 사용하는게 유리한 경우가 있고 서브쿼리를 사용하는 경우가 유리한 경우도 있다.
작동 방식의 차이
JOIN의 경우 두 개 이상의 테이블에서 관련된 열을 기준으로 데이터를 결합한다.
따라서 JOIN은 두 테이블의 행들이 서로 매칭되는 방식으로 데이터를 합쳐서 매칭된 행들의 조합으로 이루어진 확장된 테이블이다.
반면 서브쿼리는 하나의 SQL 쿼리 내에 포함된 또 다른 SQL 쿼리이다.
따라서 서브쿼리는 메인 쿼리의 결과를 계산하기 위해 메인 쿼리에 값을 제공하는 역할을 한다.
그리고 서브쿼리는 메인 쿼리의 WHERE, FROM, SELECT 절 등 다양한 곳에서 사용될 수 있다.
사용되는 경우
JOIN은 여러 테이블 간의 관계를 기반으로 복합적인 데이터 세트를 생성할 때 주로 사용된다.
예를 들어, 직원과 부서 정보가 별도의 테이블에 저장되어 있을 때 직원의 이름과 해당하는 부서 이름을 함께 조회해야 하는 경우 JOIN을 사용한다.
서브쿼리는 특정 조건에 맞는 데이터를 필터링하거나, 함수에 의해서 계산된 값을 메인 쿼리의 조건으로 사용할 때 유용하다.
예를 들어, 평균 급여보다 많은 급여를 받는 직원을 찾거나, 특정 조건을 만족하는 행의 수를 계산하는 데 서브쿼리를 사용할 수 있다.
성능과 최적화
데이터베이스의 최적화 엔진은 JOIN 작업을 효율적으로 처리하기 위한 다양한 전략을 가지고 있기 때문에 테이블 간의 관계를 탐색하고 관련 데이터를 결합하는 경우 JOIN을 사용하는 것이 더 좋은 성능을 제공한다.
서브쿼리는 데이터를 단계별로 필터링하거나 처리해야 하는 경우 쿼리의 각 단계를 명확하게 표현할 수 있어 서브쿼리 를 사용하는 것이 더 직관적이고 이해하기 쉽다.
그리고 WHERE 절에서 특정 조건을 만족하는 값에 대해 추가 계산을 수행해야 할 때와 같이 유연한 접근을 필요로 할 때는 서브쿼리를 사용하는 것이 더 좋다.