[SQL] SELECT 문법 총정리 (Oracle 기준)
이 글은 Oracle 기준으로 SELECT 문을 한 번에 정리한 글이다. 문법을 외우기보다는 “어떤 순서로 처리되는지”와 “자주 쓰는 형태”를 예제로 정리했다.
0. 예시 테이블
예시는 아래 테이블을 가정한다.
users
| 컬럼 | 설명 |
|---|---|
| id | 회원 PK |
| name | 이름 |
| 이메일 | |
| created_at | 가입일(TIMESTAMP/DATE) |
orders
| 컬럼 | 설명 |
|---|---|
| id | 주문 PK |
| user_id | 회원 FK |
| total_price | 총 금액 |
| status | 상태(PAID, CANCELED 등) |
| created_at | 주문일(TIMESTAMP/DATE) |
1. SELECT 기본 형태
1-1) 전체 조회
SELECT *
FROM users;
1-2) 특정 컬럼만 조회
SELECT id, name, email
FROM users;
1-3) 별칭(alias)
SELECT u.id, u.name, u.email
FROM users u;
1-4) 컬럼 별칭(표시 이름)
SELECT id AS user_id, name AS user_name
FROM users;
2. SELECT의 내부 실행 순서
중요한 포인트는 SELECT를 작성한 순서대로 실행되는 게 아니라, DBMS 내부에서 다음 순서로 처리된다는 점이다.
- FROM
- WHERE
- GROUP BY
- HAVING
- SELECT
- ORDER BY
이 순서를 이해하면 WHERE/HAVING 차이, 집계 처리 흐름이 깔끔하게 정리된다.
3. WHERE 조건
3-1) 비교 연산
SELECT *
FROM orders
WHERE total_price >= 10000;
3-2) AND / OR / NOT
SELECT *
FROM orders
WHERE status = 'PAID'
AND total_price >= 10000;
3-3) IN / NOT IN
SELECT *
FROM orders
WHERE status IN ('PAID', 'SHIPPED');
3-4) BETWEEN
SELECT *
FROM orders
WHERE created_at BETWEEN TO_DATE('2026-02-01', 'YYYY-MM-DD')
AND TO_DATE('2026-02-28', 'YYYY-MM-DD');
3-5) LIKE
SELECT *
FROM users
WHERE email LIKE '%@gmail.com';
3-6) NULL 체크 (Oracle은 IS NULL로)
SELECT *
FROM users
WHERE email IS NOT NULL;
NULL은 '='로 비교하지 않는다. IS NULL / IS NOT NULL만 사용한다.
4. 정렬(ORDER BY)
4-1) 오름/내림차순
SELECT *
FROM orders
ORDER BY created_at DESC;
4-2) 다중 정렬
SELECT *
FROM orders
ORDER BY status ASC, created_at DESC;
5. 집계 함수와 GROUP BY
5-1) COUNT / SUM / AVG / MIN / MAX
SELECT COUNT(*) AS cnt
FROM orders
WHERE status = 'PAID';
SELECT user_id, SUM(total_price) AS total
FROM orders
WHERE status = 'PAID'
GROUP BY user_id;
5-2) HAVING (그룹 조건)
SELECT user_id, COUNT(*) AS cnt
FROM orders
WHERE status = 'PAID'
GROUP BY user_id
HAVING COUNT(*) >= 2;
WHERE는 “행(Row)”에 조건을 걸고, HAVING은 “그룹(Group)”에 조건을 건다.
6. DISTINCT
SELECT DISTINCT status
FROM orders;
7. Oracle 페이징 (LIMIT 대신 FETCH/OFFSET)
Oracle은 MySQL처럼 LIMIT을 쓰지 않는다. 대신 OFFSET/FETCH 또는 ROWNUM을 사용한다.
7-1) OFFSET ... FETCH (권장)
SELECT id, name, created_at
FROM users
ORDER BY created_at DESC
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;
7-2) ROWNUM (구버전 호환)
SELECT *
FROM (
SELECT u.*
FROM users u
ORDER BY created_at DESC
)
WHERE ROWNUM <= 10;
ROWNUM은 ORDER BY보다 먼저 적용되는 형태로 실수하기 쉬워서, 서브쿼리로 감싸는 패턴이 안전하다.
8. Oracle 날짜/시간 자주 쓰는 것
8-1) 현재 시각
SELECT SYSDATE FROM dual;
8-2) 문자열 → 날짜 변환
SELECT TO_DATE('2026-02-07', 'YYYY-MM-DD') FROM dual;
8-3) 날짜 범위 조회 예시
SELECT *
FROM orders
WHERE created_at >= TO_DATE('2026-02-01', 'YYYY-MM-DD')
AND created_at < TO_DATE('2026-03-01', 'YYYY-MM-DD');
월 단위 조회는 “이상/미만” 형태로 끊어주는 게 실무에서 안정적이다.
9. NULL 처리 함수 (Oracle: NVL / COALESCE)
9-1) NVL
SELECT NVL(email, 'NO_EMAIL') AS email
FROM users;
9-2) COALESCE
SELECT COALESCE(email, 'NO_EMAIL') AS email
FROM users;
10. CASE (조건 분기)
SELECT
id,
total_price,
CASE
WHEN total_price >= 100000 THEN 'HIGH'
WHEN total_price >= 10000 THEN 'MID'
ELSE 'LOW'
END AS price_level
FROM orders;
11. 마무리 체크리스트
- 실행 순서: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
- NULL 비교는 IS NULL / IS NOT NULL
- Oracle 페이징은 OFFSET/FETCH 또는 ROWNUM
- 날짜는 TO_DATE 포맷을 명확히
'Computer Science > Database' 카테고리의 다른 글
| [SQL] DDL / DML / DCL / TCL 총정리 (Oracle 기준) (0) | 2026.02.13 |
|---|---|
| [DB] 11. 데이터베이스 아키텍처 (0) | 2026.02.13 |
| [DB] 10. 인덱스(Index)와 성능 최적화 (0) | 2026.02.07 |
| [DB] 09. 동시성 문제와 격리 (0) | 2026.02.07 |
| [DB] 08. 트랜잭션(Transaction)과 ACID (0) | 2026.02.07 |