프로그래머스 SQL 고득점 Kit "취소되지 않은 진료 예약 조회하기" 문제 풀이입니다. PATIENT, DOCTOR, APPOINTMENT 세 테이블을 JOIN해서 특정 날짜·특정 진료과의 취소되지 않은 예약만 조회하는 문제로, TIMESTAMP에서 날짜만 비교하는 방법과 정렬까지 정리했습니다.
문제 설명
환자 정보를 담은 PATIENT 테이블, 의사 정보를 담은 DOCTOR 테이블, 진료 예약목록을 담은 APPOINTMENT 테이블에서 2022년 4월 13일에 취소되지 않은 흉부외과(CS) 진료 예약 내역을 조회하는 문제입니다.
출력해야 하는 항목은 진료예약번호(APNT_NO), 환자이름(PT_NAME), 환자번호(PT_NO), 진료과코드(MCDP_CD), 의사이름(DR_NAME), 진료예약일시(APNT_YMD)이고, 결과는 진료예약일시 기준 오름차순으로 정렬해야 합니다.
테이블 구조
PATIENT: PT_NO(환자번호), PT_NAME(환자이름), GEND_CD(성별코드), AGE(나이), TLNO(전화번호)
DOCTOR: DR_NAME(의사이름), DR_ID(의사ID), LCNS_NO(면허번호), HIRE_YMD(고용일자), MCDP_CD(진료과코드), TLNO(전화번호)
APPOINTMENT: APNT_YMD(진료 예약일시, TIMESTAMP), APNT_NO(진료예약번호), PT_NO(환자번호), MCDP_CD(진료과코드), MDDR_ID(의사ID), APNT_CNCL_YN(예약취소여부), APNT_CNCL_YMD(예약취소날짜)
입출력 예 (결과)
APNT_NO PT_NAME PT_NO MCDP_CD DR_NAME APNT_YMD
| 46 | 오스왈드 | PT22000043 | CS | 루피 | 2022-04-13 09:00:00.000000 |
| 42 | 몬몬 | PT22000071 | CS | 루피 | 2022-04-13 12:30:00.000000 |
| 43 | 바라 | PT22000019 | CS | 니모 | 2022-04-13 15:30:00.000000 |
풀이 아이디어
세 테이블에서 필요한 컬럼을 가져와야 하므로 JOIN이 필요합니다. 연결 고리는 다음 두 가지입니다.
- PATIENT.PT_NO = APPOINTMENT.PT_NO (환자번호로 환자 정보 연결)
- DOCTOR.DR_ID = APPOINTMENT.MDDR_ID (의사ID로 의사 정보 연결)
JOIN으로 세 테이블을 합친 뒤에는 다음 조건으로 필터링합니다.
- 예약일시(APNT_YMD)가 2022년 4월 13일인 건
- 예약이 취소되지 않은 건(APNT_CNCL_YN = 'N')
- 진료과가 흉부외과(MCDP_CD = 'CS')인 건
APNT_YMD는 시각까지 포함된 TIMESTAMP 타입이라, 날짜만 비교하려면 DATE() 함수로 날짜 부분만 뽑아내야 합니다. 마지막으로 ORDER BY로 예약일시 기준 오름차순 정렬을 적용합니다.
코드
SELECT a.APNT_NO, p.PT_NAME, p.PT_NO, d.MCDP_CD, d.DR_NAME, a.APNT_YMD
FROM PATIENT p
JOIN APPOINTMENT a ON p.PT_NO = a.PT_NO
JOIN DOCTOR d ON d.DR_ID = a.MDDR_ID
WHERE DATE(a.APNT_YMD) = '2022-04-13'
AND a.APNT_CNCL_YN = 'N'
AND d.MCDP_CD = 'CS'
ORDER BY a.APNT_YMD;
코드 동작 설명
- FROM PATIENT p JOIN APPOINTMENT a ON p.PT_NO = a.PT_NO: 환자번호를 기준으로 환자 테이블과 예약 테이블을 연결해서, 예약 건마다 환자 이름을 가져올 수 있게 합니다.
- JOIN DOCTOR d ON d.DR_ID = a.MDDR_ID: 의사ID를 기준으로 의사 테이블을 추가로 연결해서, 담당 의사의 이름과 진료과 정보를 가져옵니다. d.MCDP_CD를 쓰는 이유는 문제에서 요구하는 출력 컬럼이 DOCTOR 테이블 기준 진료과코드이기 때문입니다.
- DATE(a.APNT_YMD) = '2022-04-13': APNT_YMD에는 2022-04-13 09:00:00.000000처럼 시각까지 들어있으므로, DATE() 함수로 날짜 부분만 추출해서 정확히 하루 단위로 비교합니다.
- a.APNT_CNCL_YN = 'N': 취소되지 않은(N) 예약만 걸러냅니다.
- d.MCDP_CD = 'CS': 흉부외과 진료만 걸러냅니다.
- ORDER BY a.APNT_YMD: 기본이 오름차순(ASC)이므로 별도 명시 없이도 예약일시가 빠른 순서로 정렬됩니다.
주어진 예시로 검증해보면, APPOINTMENT의 5건 중 2022-04-13에 취소되지 않은 CS 예약은 예약번호 42, 43, 46 세 건입니다(74번은 날짜가 다르고, 110번은 날짜도 다르고 취소(Y)된 건이라 제외). 이 세 건을 예약일시 순으로 정렬하면 09:00 → 12:30 → 15:30 순서가 되어, 문제에서 제시한 결과(46, 42, 43 순)와 정확히 일치합니다.
마무리
이 문제는 세 테이블을 목적에 맞게 JOIN하는 기본기와, TIMESTAMP 컬럼에서 날짜만 뽑아 비교하는 방법(DATE() 함수)을 함께 연습할 수 있는 문제입니다. 특히 "날짜만 필터링해야 하는데 컬럼 타입은 TIMESTAMP"인 상황은 실무에서도 자주 마주치는 패턴이라, DATE() 함수를 쓰는 방법과 범위 조건(>=, <)을 쓰는 방법 두 가지를 모두 알아두면 좋습니다.
'프로그래머스 > 레벨1' 카테고리의 다른 글
| [프로그래머스 MySQL] 연도별 대장균 크기의 편차 구하기 - SUM, MAX, MIN (0) | 2026.09.05 |
|---|---|
| [프로그래머스 MySQL] 조건에 부합하는 중고거래 댓글 조회하기 - SELECT (0) | 2026.09.04 |
| [MySQL] 프로그래머스 레벨1_역순 정렬하기 (0) | 2023.02.06 |
| [MySQL] 프로그래머스 레벨1_모든 레코드 조회하기 (0) | 2023.02.06 |
| [프로그래머스/자바] 나머지가 1이 되는 숫자 찾기 (0) | 2022.02.24 |