Top N, 계층형 질의, PIVOT, 정규표현식
SQL 활용 후반부의 빈출 주제인 상위 N건, 셀프 조인과 계층형 질의, PIVOT/UNPIVOT, 정규표현식을 문제 풀이용으로 압축합니다.
출제 빈도 ★★★★☆ 관련 문제 9개 |
ROWNUMCONNECT BYPIVOTREGEXP_LIKE Top N 쿼리
Top N은 정렬한 결과에서 상위 몇 건만 가져오는 쿼리입니다. 핵심은 정렬을 먼저 한 뒤 제한해야 한다는 점입니다.
-- Oracle 12c+ / SQL Server 2012+ ANSI 표준
SELECT ename, sal
FROM emp
ORDER BY sal DESC
FETCH FIRST 3 ROWS ONLY;
FETCH · OFFSET 세 가지 패턴
-- 상위 5건만
... ORDER BY sal DESC FETCH FIRST 5 ROWS ONLY;
-- 5건 건너뛴 뒤 3건
... ORDER BY sal DESC OFFSET 5 ROWS FETCH NEXT 3 ROWS ONLY;
-- 동점 포함 (급여 3위 동률이면 모두 반환)
... ORDER BY sal DESC FETCH FIRST 3 ROWS WITH TIES;
셀프 조인
셀프 조인은 같은 테이블을 두 번 사용해 자기 자신과 조인하는 방식입니다. 사원과 관리자가 같은 emp 테이블에 있을 때 자주 사용합니다.
SELECT worker.ename AS worker_name,
manager.ename AS manager_name
FROM emp worker
LEFT JOIN emp manager ON worker.mgr = manager.empno;
같은 테이블을 두 번 쓰므로 별칭이 필요합니다. 관리자가 없는 사원(KING)도 결과에 포함하려면 LEFT OUTER JOIN을 사용합니다.
계층형 질의
Oracle 계층형 질의는 부모-자식 구조(조직도, 카테고리 트리 등)를 펼칠 때 사용합니다.
SELECT LEVEL, empno, ename, mgr,
LPAD(' ', (LEVEL-1)*2) || ename AS tree
FROM emp
START WITH mgr IS NULL
CONNECT BY PRIOR empno = mgr
ORDER SIBLINGS BY ename;
| 키워드 | 의미 |
|---|---|
START WITH | 루트 행 지정 (예: mgr IS NULL은 최상위 사원) |
CONNECT BY | 부모와 자식 연결 조건 |
PRIOR | 부모 행의 컬럼을 가리킵니다 |
LEVEL | 루트는 1, 아래로 갈수록 +1 |
ORDER SIBLINGS BY | 형제(같은 부모) 노드끼리 정렬 (계층 유지) |
NOCYCLE | 순환 발생 시 오류 없이 종료 |
의사 컬럼과 계층형 함수
| 컬럼/함수 | 용도 |
|---|---|
LEVEL | 계층 깊이 (루트=1) |
CONNECT_BY_ISLEAF | 리프 노드이면 1, 아니면 0 |
CONNECT_BY_ISCYCLE | 순환 행이면 1 (NOCYCLE 시) |
CONNECT_BY_ROOT col | 각 행이 파생된 루트 값 |
SYS_CONNECT_BY_PATH(col, '/') | 루트부터 현재까지 경로 문자열 |
PIVOT과 UNPIVOT
PIVOT (행 → 열)
세로 목록을 가로 표로 요약합니다. 집계 함수가 필요합니다.
SELECT *
FROM (SELECT job, deptno, sal FROM emp)
PIVOT (
SUM(sal) FOR deptno IN (10, 20, 30)
);
암시적 GROUP BY를 수행하므로 명시하면 오류가 발생합니다.
UNPIVOT (열 → 행)
가로로 펼쳐진 열을 세로 키-값 쌍으로 변환합니다.
SELECT *
FROM sales_table
UNPIVOT (
amount FOR quarter IN (q1, q2, q3, q4)
);
집계 함수는 필요하지 않습니다. NULL 값은 기본적으로 제외됩니다 (포함하려면 INCLUDE NULLS).
정규표현식
정규표현식은 문자열 패턴을 찾거나 바꾸는 규칙입니다. SQLD에서는 함수 이름과 기본 기호를 연결하는 문제가 자주 나옵니다.
주요 메타 문자
| 기호 | 의미 | 예 |
|---|---|---|
. | 임의의 한 문자 | a.c → abc, axc |
^ | 문자열 시작 | ^A → A로 시작 |
$ | 문자열 끝 | Z$ → Z로 끝남 |
* | 0회 이상 반복 | a* |
+ | 1회 이상 반복 | [0-9]+ → 숫자 하나 이상 |
? | 0회 또는 1회 | colou?r → color, colour |
{m,n} | m회 이상 n회 이하 | a{2,4} |
[abc] | 문자 집합 | [aeiou] → 모음 |
[^abc] | 부정 집합 | 모음 제외 |
| | 또는 | cat|dog |
POSIX 문자 클래스
| 표현식 | 의미 |
|---|---|
[[:digit:]] | 숫자 [0-9] |
[[:lower:]] | 소문자 [a-z] |
[[:upper:]] | 대문자 [A-Z] |
[[:alpha:]] | 영문자 |
[[:alnum:]] | 숫자 + 영문자 |
[[:space:]] | 공백 |
Oracle 정규표현식 함수
| 함수 | 용도 |
|---|---|
REGEXP_LIKE(str, pattern) | 패턴 일치 여부 (TRUE/FALSE) |
REGEXP_REPLACE(str, pat, repl) | 패턴을 찾아 치환 (기본 전역 치환) |
REGEXP_SUBSTR(str, pattern) | 패턴에 맞는 부분 문자열 추출 |
REGEXP_INSTR(str, pattern) | 패턴 시작 위치 반환 |
REGEXP_COUNT(str, pattern) | 패턴 등장 횟수 반환 |
-- 이름이 'A'로 시작하는 사원
SELECT ename FROM emp
WHERE REGEXP_LIKE(ename, '^A');
-- 대소문자 무시 (i 옵션)
WHERE REGEXP_LIKE(ename, '^a', 'i');
Top N은 정렬 후 제한, 계층형 질의는 부모-자식 전개, PIVOT은 행과 열의 방향 전환입니다.