본문 바로가기
Language/Java

[Programmers | ORACLE | SELECT 문제 풀이] 상위 n개의 레코드 - Solution with SubQuery

by ㅇ달빛천사ㅇ 2024. 6. 4.
728x90

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절에 DATETIMEMIN(DATETIME)과 일치한다는 조건을 줌.

    SELECT NAME 
    FROM ANIMAL_INS 
    WHERE DATETIME = MIN(DATETIME);
    실행 결과
    SQL 실행 중 오류가 발생하였습니다.
      ORA-00934: group function is not allowed here
    집계함수는 WHERE절에 사용할 수 없다.

  • 그래서 혹시 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 의미, 사용법
  • 집계함수 결과와 같은 값 출력하기


📚 REFERENCES(참고 자료)

728x90


Top