<< 오라클 문법 기록장 >>
1. 고양이와 개는 몇마리 있을까
CASE문과 DECODE함수는 모두 알파벳 순서와 관계없이 원하는 순서를 지정하여 정렬할 수 있다
<< 정렬 순서에 영향을 주는 원리 >>
ORDER BY 절은 지정된 컬럼이나 표현식의 반환 값을 기준으로 데이터를 오름차순(ASC) 또는 내림차순(DESC)으로 정렬합니다.
CASE와 DECODE는 이 반환 값을 직접 지정해주는 역할을 합니다
- 쿼리 내부에서 임시 컬럼 생성
: 데이터베이스는 ORDER BY 절을 실행할 때, 보이지 않는 임시 컬럼을 생성합니다. 이 컬럼의 값은 CASE나 DECODE가 반환하는 값으로 채워집니다. - 임시 컬럼을 기준으로 정렬
: DECODE 함수에 따라 ANIMAL_TYPE이 Cat인 행의 임시 컬럼에는 1을, Dog인 행에는 2를 채워 넣습니다. - 결과 반환
: 이제 오름차순(ORDER BY의 기본값)으로 임시 컬럼을 정렬합니다. 1이 2보다 먼저 오므로, 'Cat' 행이 'Dog' 행보다 먼저 위치하게 됩니다.
최종적으로 사용자에게는 정렬된 ANIMAL_TYPE과 count 컬럼만 보입니다.
이 과정에서 임시 컬럼은 사용자에게 보이지 않습니다.
결론적으로, CASE와 DECODE는 실제 컬럼의 데이터(예: 'Cat', 'Dog')를 직접 바꾸는 것이 아니라, 정렬을 위한 '대리 값'을 생성하여 원하는 순서대로 정렬하도록 유도하는 역할을 합니다. 이 때문에 데이터 형태의 변화 없이 원하는 순서를 지정할 수 있는 것입니다.
예시: DECODE 함수의 동작 방식
SELECT ANIMAL_TYPE,
COUNT(ANIMAL_ID) AS count
FROM ANIMAL_INS
...
ORDER BY DECODE(ANIMAL_TYPE, 'Cat', 1, 'Dog', 2);
| ANIMAL_TYPE | count | 정렬을 위한 임시 컬럼 |
| Cat | 50 | 1 |
| Dog | 30 | 2 |
1) CASE문을 이용한 정렬
SELECT
ANIMAL_TYPE,
COUNT(ANIMAL_ID) AS count
FROM ANIMAL_INS
WHERE
ANIMAL_TYPE IN ('Cat', 'Dog')
GROUP BY
ANIMAL_TYPE
ORDER BY
CASE ANIMAL_TYPE
WHEN 'Cat' THEN 1
WHEN 'Dog' THEN 2
END;
2) DECODE 함수를 이용한 정렬
SELECT
ANIMAL_TYPE,
COUNT(ANIMAL_ID) AS count
FROM ANIMAL_INS
WHERE
ANIMAL_TYPE IN ('Cat', 'Dog')
GROUP BY
ANIMAL_TYPE
ORDER BY
DECODE(ANIMAL_TYPE, 'Cat', 1, 'Dog', 2);
2. 입양 시각 구하기(1)
SELECT
TO_NUMBER(TO_CHAR(DATETIME, 'HH24')) AS hour ,
COUNT(*) AS count
FROM ANIMAL_OUTS
WHERE TO_CHAR(DATETIME, 'HH24') BETWEEN 9 AND 19
GROUP BY TO_CHAR(DATETIME, 'HH24')
ORDER BY hour ASC;
1) TO_CHAR에서 HH24 포멧
TO_CHAR(datetime, 'HH24')에서 HH24는 24시간 형식의 시(hour)를 의미한다.
즉, 시간 값을 00~23 사이의 두 자리 숫자로 반환
| 포멧 | 설명 | 예시(오전 2시 5분) | 예시 (오후 2시 5분) |
| HH | 12시간 형식 (01~12) | 02 | 02 |
| HH12 | 12시간 형식 (01~12) | 02 | 02 |
| HH24 | 24시간 형식 (00~23) | 02 | 14 |
2) TO_NUMBER을 해준 이유
TO_CHAR 함수는 문자열(VARCHAR2)을 반환한다
즉, TO_CHAR(datetime, 'HH24')는 '09', '10', '11' 이런 문자열로 나오게 된다.
그 다음 TO_NUMBER로 감싸면 이 문자열은 숫자로 변환되는데 이렇게 처리했을 때 좋은 점이 3가지 있다
- 첫번째, 출력 시 숫자처럼 보이게 할 수 있다
- 두번째 ORDER BY에서 '09','10'등 문자열이 정렬 오류를 일으키는 것을 방지할 수 있다
- 세번째 , 숫자 연산을 할 수 있다.
3. Oracle에는 DATETIME 의 데이터 타입은 없다
Oracle에는 DATETIME이란 데이터 타입은 없다.
대신 DATE와 TIMESTAMP 형태의 데이터 타입은 있다
이번 문제를 풀 때 EXTRACT를 사용하려다 에러를 만났는데
그 이유는 소스 타입이 DATE인데 EXTRACT(HOUR FROM DATETIME)을 썼기 때문이었다
Oracle에서 EXTRACT는 DATE에서 YEAR,MONTH,DAY는 뽑을 수 있지만
HOUR,MINUTE,SECOND는 TIMESTAMP에서만 뽑을 수 있다.
- 해결방법
1. TIMESTAMP로 캐스팅해서 사용(해당 값의 표현타입을 TIMESTAMP로 임시변환해서사용하는 것 )
SELECT EXTRACT(HOUR FROM CAST(datetime AS TIMESTAMP)) AS hour,
COUNT(*) AS cnt
FROM animal_outs
WHERE EXTRACT(HOUR FROM CAST(datetime AS TIMESTAMP)) BETWEEN 9 AND 19
GROUP BY EXTRACT(HOUR FROM CAST(datetime AS TIMESTAMP))
ORDER BY hour;
2. TO_CHAR를 그대로 사용 (제출답안처럼)
3. 나머지 문제
진료과별 총 예약 횟수 출력하기
SELECT
MCDP_CD AS "진료과코드",
COUNT(PT_NO) AS "5월예약건수"
FROM APPOINTMENT
WHERE TO_CHAR(APNT_YMD, 'YYYY-MM') = '2022-05'
GROUP BY MCDP_CD
ORDER BY COUNT(PT_NO),MCDP_CD;
자동차 종류별 특정 옵션이 포함된 자동차 수 구하기
SELECT
CAR_TYPE,
COUNT(CAR_ID) AS CARS
FROM CAR_RENTAL_COMPANY_CAR
WHERE
OPTIONS LIKE '%통풍시트%'
OR OPTIONS LIKE '%열선시트%'
OR OPTIONS LIKE '%가죽시트%'
GROUP BY CAR_TYPE
ORDER BY CAR_TYPE;
'코딩 테스트 > 02. SQL' 카테고리의 다른 글
| [프로그래머스] Oracle SQL_1(Lv3) (0) | 2025.09.19 |
|---|---|
| [프로그래머스]Oracle SQL_2(Lv2) (0) | 2025.09.16 |
| [프로그래머스]Oracle SQL(Lv2,10문제) (0) | 2025.09.12 |
| [프로그래머스] Oracle SQL (Lv1, 24문제) (1) | 2025.09.11 |
| [Hacker Rank] SQL Intermediate 'Symmetric Pairs' (Medium) (4) | 2025.08.22 |