스칼라 서브쿼리
SELECT name, score
FROM students
WHERE score > (SELECT AVG(score) FROM students);
한 값을 기대해서 비교합니다.
IN / NOT IN
SELECT name FROM users
WHERE id IN (SELECT user_id FROM orders);
NOT IN에 서브쿼리 결과가 NULL을 포함하면 전체가 이상해질 수 있습니다.
없을 때는 LEFT JOIN … WHERE right.id IS NULL 또는 NOT EXISTS가 더 안전합니다.
EXISTS
SELECT u.name
FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);
존재 여부만 볼 때 효율·의미 모두 명확합니다.
파생 테이블
SELECT city, cnt
FROM (
SELECT city, COUNT(*) AS cnt FROM users GROUP BY city
) t
WHERE cnt >= 2;
SQLite에서는 서브쿼리에 별칭이 필요합니다.
JOIN vs 서브쿼리
같은 문제를 둘 다로 풀 수 있을 때가 많습니다.
가독성·중복 행 여부를 기준으로 고르세요.
인라인 뷰
SELECT *
FROM (
SELECT user_id, COUNT(*) AS cnt
FROM orders
GROUP BY user_id
) t
WHERE cnt >= 2;
FROM 절 서브쿼리에 별칭이 필요합니다(엔진마다).
IN 과 NULL
IN (SELECT ...) 결과에 NULL이 섞이면 논리가 意外해질 수 있습니다.
연습 데이터에서 NULL을 의식하세요.
상관 서브쿼리
바깥 행의 컬럼을 안쪽에서 참조합니다.
작인 데이터에서는 괜찮고, 커지면 JOIN·집계로 바꾸는 편이 낫습니다.