[SQL] SELECT 문법 총정리 (Oracle 기준)

[SQL] SELECT 문법 총정리 (Oracle 기준)

이 글은 Oracle 기준으로 SELECT 문을 한 번에 정리한 글이다. 문법을 외우기보다는 “어떤 순서로 처리되는지”와 “자주 쓰는 형태”를 예제로 정리했다.

0. 예시 테이블

예시는 아래 테이블을 가정한다.

users

컬럼 설명
id 회원 PK
name 이름
email 이메일
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 내부에서 다음 순서로 처리된다는 점이다.

  1. FROM
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. SELECT
  6. 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 포맷을 명확히