서브쿼리
Subquery
쿼리 안의 쿼리. 복잡한 조건 표현.
Subquery
쿼리 안의 쿼리. 복잡한 조건 표현.
서브쿼리(Subquery)는 SQL 문 안에 포함된 또 다른 SELECT 문으로, 외부 쿼리가 사용할 결과를 제공합니다. 중첩 쿼리(Nested Query)라고도 부르며, WHERE, FROM, SELECT 절 등 다양한 위치에서 사용할 수 있습니다.
서브쿼리는 크게 스칼라 서브쿼리(단일 값 반환), 인라인 뷰(FROM 절에서 사용), 상관 서브쿼리(외부 쿼리 참조)로 구분됩니다. 복잡한 조건이나 계산이 필요할 때 유용하지만, 과도한 사용은 성능 저하를 유발할 수 있습니다.
일부 서브쿼리는 JOIN으로 변환하여 성능을 개선할 수 있습니다. 쿼리 옵티마이저가 자동으로 최적화하기도 하지만, 개발자가 의도적으로 변환하면 더 나은 실행 계획을 얻을 수 있습니다.
-- 스칼라 서브쿼리 (SELECT 절)
SELECT
name,
salary,
(SELECT AVG(salary) FROM employees) as avg_salary
FROM employees;
-- WHERE 절 서브쿼리
SELECT name, department
FROM employees
WHERE department_id IN (
SELECT id FROM departments
WHERE location = 'Seoul'
);
-- 상관 서브쿼리 (Correlated Subquery)
SELECT e.name, e.salary
FROM employees e
WHERE e.salary > (
SELECT AVG(salary)
FROM employees
WHERE department_id = e.department_id
);
-- EXISTS 서브쿼리
SELECT c.name
FROM customers c
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.id
AND o.order_date > '2024-01-01'
);
-- 인라인 뷰 (FROM 절 서브쿼리)
SELECT dept_name, avg_salary
FROM (
SELECT d.name as dept_name, AVG(e.salary) as avg_salary
FROM departments d
JOIN employees e ON d.id = e.department_id
GROUP BY d.name
) dept_stats
WHERE avg_salary > 5000000;
백엔드 개발자: 이 쿼리 너무 느린데, 서브쿼리가 여러 개 중첩되어 있어요.
DBA: 상관 서브쿼리네요. 외부 쿼리 행마다 서브쿼리가 실행되니까 느릴 수밖에요.
백엔드 개발자: JOIN으로 바꾸면 나아질까요?
DBA: 네, 대부분의 경우 JOIN이 더 효율적이에요. 옵티마이저가 실행 계획을 더 잘 세울 수 있거든요.
면접관: 서브쿼리와 JOIN의 차이점과 어떤 상황에서 서브쿼리를 사용하시나요?
지원자: 서브쿼리는 복잡한 조건이나 단일 값을 구할 때 가독성이 좋습니다. 하지만 상관 서브쿼리는 행마다 실행되어 성능 이슈가 있어서, 가능하면 JOIN으로 변환하는 게 좋습니다. EXISTS는 데이터 존재 여부만 확인할 때 효율적입니다.
면접관: 스칼라 서브쿼리의 주의점은요?
지원자: 스칼라 서브쿼리는 반드시 단일 행, 단일 열을 반환해야 합니다. 여러 행이 반환되면 에러가 발생해요.
시니어: 이 코드에서 서브쿼리가 세 번이나 같은 테이블을 조회하네요.
주니어: 네, 조건마다 필요해서요.
시니어: WITH 절(CTE)로 한 번 조회해서 재사용하거나, JOIN으로 리팩토링하면 성능이 훨씬 좋아질 거예요. 서브쿼리 중복은 피해야 합니다.