KDT 실무형 스프링 백엔드 엔지니어 양성과정 6기 | SQL CODEKATA
1️⃣ 상위 n개의 레코드
🏷 Topic : SELECT SUBQUERY 집계함수 MIN ROWNUM
문제 설명
ANIMAL_INS 테이블은 동물 보호소에 들어온 동물의 정보를 담은 테이블입니다. ANIMAL_INS 테이블 구조는 다음과 같으며, ANIMAL_ID, ANIMAL_TYPE, DATETIME, INTAKE_CONDITION, NAME, SEX_UPON_INTAKE는 각각 동물의 아이디, 생물 종, 보호 시작일, 보호 시작 시 상태, 이름, 성별 및 중성화 여부를 나타냅니다.
| NAME | TYPE | NULLABLE |
|---|---|---|
| ANIMAL_ID | VARCHAR(N) | FALSE |
| ANIMAL_TYPE | VARCHAR(N) | FALSE |
| DATETIME | DATETIME | FALSE |
| INTAKE_CONDITION | VARCHAR(N) | FALSE |
| NAME | VARCHAR(N) | TRUE |
| SEX_UPON_INTAKE | VARCHAR(N) | FALSE |
동물 보호소에 가장 먼저 들어온 동물의 이름을 조회하는 SQL 문을 작성해주세요.
예시
예를 들어 ANIMAL_INS 테이블이 다음과 같다면
| ANIMAL_ID | ANIMAL_TYPE | DATETIME | INTAKE_CONDITION | NAME | SEX_UPON_INTAKE |
|---|---|---|---|---|---|
| A399552 | Dog | 2013-10-14 15:38:00 | Normal | Jack | Neutered Male |
| A379998 | Dog | 2013-10-23 11:42:00 | Normal | Disciple | Intact Male |
| A370852 | Dog | 2013-11-03 15:04:00 | Normal | Katie | Spayed Female |
| A403564 | Dog | 2013-11-18 17:03:00 | Normal | Anna | Spayed Female |
이 중 가장 보호소에 먼저 들어온 동물은 Jack입니다. 따라서 SQL문을 실행하면 다음과 같이 나와야 합니다.
| NAME |
|---|
| Jack |
※ 보호소에 가장 먼저 들어온 동물은 한 마리인 경우만 테스트 케이스로 주어집니다.
본 문제는 Kaggle의 "Austin Animal Center Shelter Intakes and Outcomes"에서 제공하는 데이터를 사용하였으며 ODbL의 적용을 받습니다.
✔ Solution with WHERE절 SUBQUERY & 집계함수 MIN
SELECT NAME
FROM ANIMAL_INS
WHERE DATETIME = (SELECT MIN(DATETIME)
FROM ANIMAL_INS);실행 결과

✔ Solution with FROM절 SUBQUERY & ORDER BY & ROWNUM
SELECT NAME
FROM (SELECT NAME
FROM ANIMAL_INS
ORDER BY DATETIME)
WHERE ROWNUM = 1;실행 결과

💥 오늘 만난 문제 & 나의 시도 💦 & 해결 방법 👍
📌 문제의 요점 : 동물 보호소에 가장 먼저 들어온 동물의 이름을 조회하는 SQL 문을 작성해주세요.
'가장 먼저 들어 온'이라는 의미는 DATETIME이 가장 오래된 동물의 이름을 출력하면 된다.
1. ROWNUM을 이용한 방법 시도
처음에 인터넷으로 검색을 해서 찾은
ROWNUM을 이용해서 QUERY를 써 보았다.SELECT NAME FROM ANIMAL_INS WHERE ROWNUM = 1 ORDER BY DATETIME;실행 결과
Jack이 아니라 Sugar가 출력됨😕
ROWNUM이 출력된 첫번째 행을 1로 행 번호가 순차적으로 매겨지는 줄 알았는데 아니었나 보다.
SELECT ROWNUM , NAME FROM ANIMAL_INS ORDER BY DATETIME;실행 결과
실행 결과의 ROWNUM이 순차적이지 않고 뒤죽박죽되어 있는 것을 확인할 수 있다.
ORDER BY절이 ROWNUM보다 나중에 매겨지는 것 같다.
그래서 위의 코드를 FROM절의 서브쿼리로 줘서 문제를 풀어 보았다.
SELECT NAME FROM(SELECT NAME FROM ANIMAL_INS ORDER BY DATETIME) WHERE ROWNUM = 1;실행 결과
🎉 이번에는 제대로 Jack이 출력됨 🎉
2. 집계함수 MIN과 WHERE절 서브쿼리를 이용한 방법
처음에 WHERE절에
DATETIME이MIN(DATETIME)과 일치한다는 조건을 줌.SELECT NAME FROM ANIMAL_INS WHERE DATETIME = MIN(DATETIME);실행 결과
집계함수는 WHERE절에 사용할 수 없다.SQL 실행 중 오류가 발생하였습니다. ORA-00934: group function is not allowed here
그래서 혹시
GROUP BY DATETIME을 하고 HAVING 절에 집계함수를 쓰면 될까? 해서 코드를 써 봄.SELECT NAME FROM ANIMAL_INS GROUP BY DATETIME HAVING DATETIME = MIN(DATETIME);실행 결과
SQL 실행 중 오류가 발생하였습니다. ORA-00979: not a GROUP BY expression
위의 코드도 에러가 나서 인터넷에 검색을 해 보니 서브쿼리로 주면 된다고 함.
SELECT NAME FROM ANIMAL_INS WHERE DATETIME = (SELECT MIN(DATETIME) FROM ANIMAL_INS);실행 결과
🎉 Jack 출력 성공! 🎉
💬 무엇을 새롭게 알았는지
- ROWNUM 의미, 사용법
- 집계함수 결과와 같은 값 출력하기