에듀테크 프로젝트 대시보드
서브쿼리와 CTE
쿼리 안의 쿼리. WITH(CTE)로 이름을 붙이면 복잡한 로직도 위에서 아래로 읽힙니다.
-- 스칼라 (값 하나)
SELECT name, (SELECT count(*) FROM exams e WHERE e.student_id = s.id) AS 시험수
FROM students s;
-- IN / EXISTS
SELECT * FROM students
WHERE id IN (SELECT student_id FROM exams WHERE score = 100);
SELECT * FROM students s
WHERE EXISTS (SELECT 1 FROM exams e WHERE e.student_id = s.id AND e.score = 100);NOT IN 은 함정 — NOT EXISTS 를 쓰세요WITH recent AS (
SELECT * FROM exams WHERE exam_date >= now() - interval '30 days'
),
ranked AS (
SELECT student_id, score,
rank() OVER (ORDER BY score DESC) AS rnk
FROM recent
)
SELECT s.name, r.score, r.rnk
FROM ranked r JOIN students s ON s.id = r.student_id
WHERE r.rnk <= 10;-- 조직도: 특정 사원의 모든 하위 사원
WITH RECURSIVE subtree AS (
SELECT id, name, manager_id FROM employees WHERE id = 1 -- 시작점
UNION ALL
SELECT e.id, e.name, e.manager_id
FROM employees e JOIN subtree t ON e.manager_id = t.id -- 재귀
)
SELECT * FROM subtree;WITH x AS MATERIALIZED (...) / NOT MATERIALIZED-- 옮기면서 삭제 (원자적)
WITH moved AS (
DELETE FROM events WHERE created_at < '2025-01-01' RETURNING *
)
INSERT INTO events_archive SELECT * FROM moved;