정보처리기사2026년 4월 16일· 10 min read· 조회 0

정처기 실기 SQL 정리 (JOIN·서브쿼리·윈도우 함수)

정처기 실기 SQL 파트에서 결과값 예측에 필요한 JOIN, GROUP BY, HAVING, 서브쿼리, 윈도우 함수(RANK·ROW_NUMBER·LAG)를 예제 중심으로 정리합니다.

안녕하세요. 문어입니다 🐙


결론 먼저

정처기 실기 SQL은 JOIN, GROUP BY/HAVING, 윈도우 함수 세 주제에서 결과 테이블을 손으로 그릴 수 있으면 대부분 풀립니다. 이 글에서는 각 주제의 출제 형태·결과 예시·자주 하는 실수를 정리해요.


왜 '눈으로' 풀면 틀리는가

실기 SQL 문제는 대부분 쿼리를 주고 결과 테이블을 쓰라는 식입니다. 문법 객관식이 아니라 실행 결과를 직접 작성해야 해서, 머릿속으로만 훑으면 JOIN 결과 행 개수·NULL 처리·집계 컬럼 같은 지점에서 쉽게 틀립니다.

문법을 외우는 것으로는 부족하고, 결과 테이블을 연필로 그려낼 수 있어야 풀 수 있는 과목이에요.


JOIN — 네 가지 종류와 결과

예시 테이블을 기준으로 설명할게요.

EMP 테이블

emp_idnamedept_id
110
220
3NULL

DEPT 테이블

dept_iddept_name
10개발
20영업
30인사

INNER JOIN

SELECT e.name, d.dept_name
FROM   EMP e
JOIN   DEPT d ON e.dept_id = d.dept_id;
namedept_name
개발
영업

양쪽 모두 매칭되는 행만 나옵니다. dept_idNULL인 이씨와, 직원이 없는 인사부서는 빠집니다.

LEFT OUTER JOIN

SELECT e.name, d.dept_name
FROM   EMP e
LEFT JOIN DEPT d ON e.dept_id = d.dept_id;
namedept_name
개발
영업
NULL

왼쪽(EMP)은 전부 나오고, 매칭 안 되는 오른쪽은 NULL로 채워집니다.

RIGHT OUTER JOIN

반대로 오른쪽(DEPT)을 기준으로 전부 나옵니다.

namedept_name
개발
영업
NULL인사

FULL OUTER JOIN

양쪽을 모두 포함. 매칭 안 되는 쪽은 NULL.

namedept_name
개발
영업
NULL
NULL인사
JOIN 결과 행 개수를 묻는 문제에서 가장 많이 틀리는 지점은 NULL 처리와 양쪽 미매칭 행의 유무입니다. 표를 직접 그려 매칭되는지 확인하세요.

GROUP BY와 HAVING

SELECT dept_id, COUNT(*) AS cnt
FROM   EMP
GROUP BY dept_id
HAVING COUNT(*) >= 2;
  • GROUP BY로 묶고, 묶은 그룹에 대한 조건은 HAVING
  • 일반 조건은 WHERE, 집계 결과에 대한 조건은 HAVING

WHERE vs HAVING

구분적용 시점집계 함수 사용
WHEREGROUP BY 전불가
HAVINGGROUP BY 후가능
-- 급여가 100 이상인 직원만 대상으로, 부서별 인원 3명 이상
SELECT dept_id, COUNT(*)
FROM   EMP
WHERE  salary >= 100          -- 행 필터링
GROUP BY dept_id
HAVING COUNT(*) >= 3;         -- 그룹 필터링

서브쿼리 — 단일행 / 다중행 / 상관

단일행 서브쿼리

SELECT *
FROM   EMP
WHERE  salary = (SELECT MAX(salary) FROM EMP);

서브쿼리 결과가 한 행일 때 =, >, < 사용.

다중행 서브쿼리

SELECT *
FROM   EMP
WHERE  dept_id IN (SELECT dept_id FROM DEPT WHERE location = 'Seoul');

여러 행일 때는 IN, ANY, ALL.

연산자의미
IN리스트 중 하나와 같으면 참
ANY조건을 만족하는 값이 하나라도 있으면 참
ALL모든 값을 만족해야 참

상관 서브쿼리

외부 쿼리의 컬럼을 서브쿼리가 참조하는 구조.

-- 각 부서 평균 급여 이상을 받는 직원
SELECT e.name, e.salary
FROM   EMP e
WHERE  e.salary >= (SELECT AVG(salary)
                    FROM EMP
                    WHERE dept_id = e.dept_id);

외부 쿼리의 e.dept_id를 내부에서 참조하므로, 서브쿼리가 각 외부 행마다 실행됩니다.


윈도우 함수 — RANK / DENSE_RANK / ROW_NUMBER

집계 함수와 달리 행을 줄이지 않고 순위·누계 등을 계산합니다.

SELECT name, salary,
       RANK()       OVER (ORDER BY salary DESC) AS r,
       DENSE_RANK() OVER (ORDER BY salary DESC) AS dr,
       ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn
FROM   EMP;
namesalaryrdrrn
A500111
B400222
C400223
D300434

차이를 정리하면 이렇습니다.

함수동점 처리다음 순위
RANK같은 순위 부여건너뜀(1, 2, 2, 4)
DENSE_RANK같은 순위 부여건너뛰지 않음(1, 2, 2, 3)
ROW_NUMBER행마다 유일한 번호순차(1, 2, 3, 4)
단답으로 "RANK와 DENSE_RANK 차이"를 물을 때가 있습니다. 핵심은 '건너뛰는가 아닌가'입니다.

LAG / LEAD

SELECT name, salary,
       LAG(salary, 1)  OVER (ORDER BY hire_date) AS prev_sal,
       LEAD(salary, 1) OVER (ORDER BY hire_date) AS next_sal
FROM   EMP;
  • LAG(col, n) : n행 이전
  • LEAD(col, n) : n행 다음

PARTITION BY

SELECT name, dept_id, salary,
       RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS dept_rank
FROM   EMP;

부서별로 순위를 별도 계산. GROUP BY처럼 묶되 행 수는 유지합니다.


집합 연산

SELECT name FROM EMP_A
UNION          -- 중복 제거 합집합
SELECT name FROM EMP_B;

SELECT name FROM EMP_A
UNION ALL      -- 중복 포함 합집합
SELECT name FROM EMP_B;

SELECT name FROM EMP_A
INTERSECT      -- 교집합
SELECT name FROM EMP_B;

SELECT name FROM EMP_A
MINUS          -- 차집합 (Oracle 문법, 표준은 EXCEPT)
SELECT name FROM EMP_B;

UNIONUNION ALL의 차이는 중복 제거 여부. 데이터 양이 많을 때는 UNION ALL이 훨씬 빠릅니다.


NULL 연산 주의

SELECT NULL = NULL;      -- NULL (true가 아님)
SELECT NULL IS NULL;     -- true
SELECT 10 + NULL;        -- NULL (모든 산술 연산이 NULL이 됨)
SELECT COUNT(*)          -- 전체 행 수
FROM emp;
SELECT COUNT(salary)     -- salary가 NULL이 아닌 행 수
FROM emp;

NULL 비교에는 IS NULL / IS NOT NULL만 사용해야 합니다. = NULL은 항상 거짓도 참도 아닌 NULL을 반환해서 행이 걸러져 나오지 않아요.


시험에서 자주 틀리는 포인트

함정핵심
JOIN 결과 행 개수NULL 처리 + 매칭 안 되는 행 포함 여부
WHERE vs HAVINGWHERE는 행 단위, HAVING은 그룹 단위
RANK vs DENSE_RANK건너뛰는가(RANK) vs 연속(DENSE_RANK)
COUNT(*) vs COUNT(col)전자는 행 전체, 후자는 NULL 제외
UNION vs UNION ALL중복 제거 여부
쿼리를 보면 실행 순서를 먼저 떠올려 보세요. FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. 이 순서만 기억해도 헷갈림이 크게 줄어요.

시험장에서의 접근법

실기에서 SQL 문제를 받으면 이 순서로 풀어보세요.

  1. 테이블 스키마·샘플 데이터를 먼저 메모지에 옮겨 적기 — 쿼리만 보지 말고 실제 데이터를 앞에 두고 시작
  2. JOIN·WHERE 적용 후 남는 행 옆에 작게 표시 (체크/X)
  3. GROUP BY가 있으면 그룹별로 묶은 후 집계 컬럼 계산
  4. HAVING이 있으면 그룹 필터링, ORDER BY는 맨 마지막에 정렬
  5. NULL이 포함된 컬럼이 나오면 = 비교가 아닌지 한 번 더 체크

긴 쿼리일수록 쿼리 안에서 실행 순서(FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY)를 머릿속에서 재배치해 풀어야 실수가 줄어요.


정리

SQL은 결과 테이블을 연필로 직접 만들어 볼 수 있는가가 합격의 조건입니다. 특히 JOIN과 윈도우 함수는 문제를 보자마자 결과 형태를 머릿속에 그릴 수 있을 때까지 몇 가지 패턴을 반복 연습하는 게 가장 빠른 길이에요.

정처기 실기 모의고사로 SQL 유형 풀어보기 →


관련 글

직접 문제를 풀어보세요

매번 새로운 모의고사와 무한 풀이 모드로 실전 감각을 키울 수 있습니다.