프로그래머스 고득점 Kit와 코딩테스트 SQL 문제를 풀다 서브쿼리가 헷갈리는 경우가 많아 이번 기회에 서브쿼리를 정리하고자 한다.
다만 GROUP BY절에는 서브쿼리를 사용할 수 없다.
SELECT
emp_name,
salary,
(SELECT AVG(salary) FROM employees) AS avg_salary,
(SELECT dept_name FROM departments d WHERE d.dept_id = e.dept_id) AS dept_name
FROM employees e;
SELECT
dept_summary.dept_id,
dept_summary.avg_salary,
d.dept_name
FROM (
SELECT
dept_id,
AVG(salary) as avg_salary,
COUNT(*) as emp_count
FROM employees
GROUP BY dept_id
) dept_summary
JOIN departments d ON dept_summary.dept_id = d.dept_id
WHERE dept_summary.avg_salary > 5000;
=
, >
, <
, >=
, <=
, <>
(같지 않다)-- 평균 급여보다 높은 급여를 받는 직원
SELECT emp_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
-- 최고 급여를 받는 직원
SELECT emp_name, salary
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);
IN
, ANY
, ALL
, EXISTS
연산자연산자 | 의미 |
---|---|
IN | 같은 값을 찾음 |
> ANY | 최솟값을 반환 |
< ANY | 최댓값을 반환 |
< ALL | 최솟값을 반환 |
> ALL | 최댓값을 반환 |
ALL(2000, 3000) : 최대값(3000)보다 큰 행들 반환
< ALL(2000, 3000) : 최소값(2000)보다 작은 행들 반환
ANY(2000, 3000) : 최소값(2000)보다 큰 행들 반환
< ANY(2000, 3000) : 최대값(3000)보다 작은 행들 반환
-- IN 사용: 서울에 있는 부서의 직원들
SELECT emp_name, dept_id
FROM employees
WHERE dept_id IN (
SELECT dept_id
FROM departments
WHERE location = '서울'
);
-- ANY 사용: 어떤 부서의 평균급여보다라도 높은 급여를 받는 직원
SELECT emp_name, salary
FROM employees
WHERE salary > ANY (
SELECT AVG(salary)
FROM employees
GROUP BY dept_id
);
-- ALL 사용: 모든 부서의 평균급여보다 높은 급여를 받는 직원
SELECT emp_name, salary
FROM employees
WHERE salary > ALL (
SELECT AVG(salary)
FROM employees
GROUP BY dept_id
);
-- 각 부서별 최고급여와 최소급여를 동시에 받는 직원
SELECT emp_name, dept_id, salary
FROM employees
WHERE (dept_id, salary) IN (
SELECT dept_id, MAX(salary)
FROM employees
GROUP BY dept_id
UNION
SELECT dept_id, MIN(salary)
FROM employees
GROUP BY dept_id
);
-- 특정 부서의 특정 직급과 일치하는 직원
SELECT emp_name, dept_id, job_title
FROM employees
WHERE (dept_id, job_title) = (
SELECT dept_id, job_title
FROM employees
WHERE emp_name = '김철수'
);
-- 같은 부서 내에서 평균급여보다 높은 급여를 받는 직원
SELECT emp_name, dept_id, salary
FROM employees e1
WHERE salary > (
SELECT AVG(salary)
FROM employees e2
WHERE e2.dept_id = e1.dept_id -- 외부 쿼리 참조
);
-- EXISTS 사용: 부하직원이 있는 매니저
SELECT emp_name, emp_id
FROM employees manager
WHERE EXISTS (
SELECT 1
FROM employees subordinate
WHERE subordinate.manager_id = manager.emp_id -- 외부 쿼리 참조
);
-- NOT EXISTS 사용: 부하직원이 없는 직원
SELECT emp_name, emp_id
FROM employees e1
WHERE NOT EXISTS (
SELECT 1
FROM employees e2
WHERE e2.manager_id = e1.emp_id
);
SELECT EMPNO, ENAME, SAL, DEPTNO
FROM EMP E1
WHERE SALARY > (SELECT AVG(SALARY)
FROM EMP E2
WHERE E1.DEPTNO = E2.DEPTNO
GROUP BY DEPTNO);
SELECT *
FROM EMP
WHERE SAL IN (SELECT SALARY
FROM EMP
WHERE DEPTNUM = 20
ORDER BY SALARY);
위와 같이 작성하면 에러가 발생한다.