본문 바로가기
SQL 문제 풀기/1. 프로그래머스 SQL : 2023.12.17~2024.2.29

<프로그래머스 52> 오랜 기간 보호한 동물(2)(Lv.3)

by HYEHYE_SON 2024. 2. 6.
728x90

 

프로그래머스에서 제공하는 SQL문제 매일 풀기 챌린지


 

문제 설명

ANIMAL_INS 테이블은 동물 보호소에 들어온 동물의 정보를 담은 테이블입니다. ANIMAL_INS 테이블 구조는 다음과 같으며, ANIMAL_IDANIMAL_TYPEDATETIMEINTAKE_CONDITIONNAMESEX_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

 

ANIMAL_OUTS 테이블은 동물 보호소에서 입양 보낸 동물의 정보를 담은 테이블입니다. ANIMAL_OUTS 테이블 구조는 다음과 같으며, ANIMAL_ID, ANIMAL_TYPE, DATETIME, NAME, SEX_UPON_OUTCOME는 각각 동물의 아이디, 생물 종, 입양일, 이름, 성별 및 중성화 여부를 나타냅니다. ANIMAL_OUTS 테이블의 ANIMAL_ID는 ANIMAL_INS의 ANIMAL_ID의 외래 키입니다.

 

NAME TYPE NULLABLE
ANIMAL_ID VARCHAR(N) FALSE
ANIMAL_TYPE VARCHAR(N) FALSE
DATETIME DATETIME FALSE
NAME VARCHAR(N) TRUE
SEX_UPON_OUTCOME VARCHAR(N) FALSE

문제

입양을 간 동물 중, 보호 기간이 가장 길었던 동물 두 마리의 아이디와 이름을 조회하는 SQL문을 작성해주세요. 이때 결과는 보호 기간이 긴 순으로 조회해야 합니다.

예시

예를 들어, ANIMAL_INS 테이블과 ANIMAL_OUTS 테이블이 다음과 같다면

 

[ ANIMAL_INS ]

ANIMAL_ID ANIMAL_TYPE DATETIME INTAKE_CONDITION NAME SEX_UPON_INTAKE
A354597 Cat 2014-05-02 12:16:00 Normal Ariel Spayed Female
A362707 Dog 2016-01-27 12:27:00 Sick Girly Girl Spayed Female
A370507 Cat 2014-10-27 14:43:00 Normal Emily Spayed Female
A414513 Dog 2016-06-07 09:17:00 Normal Rocky Neutered Male

 

[ ANIMAL_OUTS ]

ANIMAL_ID ANIMAL_TYPE DATETIME NAME SEX_UPON_OUTCOME
A354597 Cat 2014-06-03 12:30:00 Ariel Spayed Female
A362707 Dog 2017-01-10 10:44:00 Girly Girl Spayed Female
A370507 Cat 2015-08-15 09:24:00 Emily Spayed Female

 

SQL문을 실행하면 다음과 같이 나와야 합니다.

ANIMAL_ID NAME
A362707 Girly Girl
A370507 Emily

 

※ 입양을 간 동물이 2마리 이상인 경우만 입력으로 주어집니다.

 

 

본 문제는 Kaggle의 "Austin Animal Center Shelter Intakes and Outcomes"에서 제공하는 데이터를 사용하였으며 ODbL의 적용을 받습니다.


♥ 오라클 정답

select d.animal_id, d.name
from(select o.animal_id, o.name, (o.datetime - i.datetime) protect_time
    from animal_ins i, animal_outs o
    where i.animal_id = o.animal_id) d
order by protect_time desc fetch first 2 rows only;

 

 MySQL 정답

select d.animal_id, d.name
from(select o.animal_id, o.name, datediff(o.datetime, i.datetime) protect_time
    from animal_ins i, animal_outs o
    where i.animal_id = o.animal_id) d
order by protect_time desc limit 2;

 


해설해보기


이 문제는 EQUI JOIN 과 인라인뷰(from절의 서브쿼리)를 사용해서 풀 수 있다.

 

■ 인라인뷰

in line view의 select절에 필요한 컬럼들을 기입해준다.

이때 입양 간 동물의 보호기간은

animal_outs 테이블의 datetime에서 animal_ins의 datetime의 차로 구할 수 있다.

따라서 두 테이블을 EQUI JOIN 하여

서로 연결된 컬럼인 ANIMAL_IDF로 연결해준다.

 

단, 오라클에서는 마이너스 기호로 date의 차를 구할 수 있지만,

MySQL 에서는 datediff() 함수를 사용해서 차를 구해줘야한다.

 

▶ DATEDIFF( A, B )

DATE TYPE의 DATA FORMAT을 가진

값에 대하여 A-B를 구하는 함수이다.


■ 메인쿼리

메인쿼리의 SELECT절에 출력해야할 컬럼명을 입력해주는데,

FROM절에서 가져온 animal_id와 name을 기입해준다.

 

메인쿼리에서 중요한 것은 

order by 절에 있다.

 

문제의 조건이 입양을 간 동물 중 보호 기간이 가장 길었던 동물 2마리에 대해서만 조회하는 것이다.

이 조건을 order by절에서 충족시켜줄 수 있다.

 

- -오라클의 경우

order by protect_time desc 로 우선 정렬조건을 준 후 

정렬된 것을 기준으로 fetch first 2 rows only;를 사용해준다.

 

desc fetch first 2 rows only

desc하게 정렬된 것을 기준으로 맨 위에서 (처음부터)

오직 2개의 행만 출력한다는 의미이다.

 

--MySQL의 경우

order by protect_time desc 로 우성 정렬조건을 준 후

정렬된 것을 기준으로 limit 2; 를 사용해준다.

 

desc limit2

desc 하게 정렬된 것을 기준으로 2개만 출력하는 것으로 제한하는 것이다.

 


 

결과 출력

 

출처 : 프로그래머스 코딩 테스트 연습, https://school.programmers.co.kr/learn/challenges

반응형