프로그래머스에서 제공하는 SQL문제 매일 풀기 챌린지
문제 설명
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 |
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 |
문제
천재지변으로 인해 일부 데이터가 유실되었습니다. 입양을 간 기록은 있는데, 보호소에 들어온 기록이 없는 동물의 ID와 이름을 ID 순으로 조회하는 SQL문을 작성해주세요.
예시
예를 들어, ANIMAL_INS 테이블과 ANIMAL_OUTS 테이블이 다음과 같다면
[ ANIMAL_INS ]
ANIMAL_ID | ANIMAL_TYPE | DATETIME | INTAKE_CONDITION | NAME | SEX_UPON_INTAKE |
A352713 | Cat | 2017-04-13 16:29:00 | Normal | Gia | Spayed Female |
A350375 | Cat | 2017-03-06 15:01:00 | Normal | Meo | Neutered Male |
[ ANIMAL_OUTS ]
ANIMAL_ID | ANIMAL_TYPE | DATETIME | NAME | SEX_UPON_OUTCOME |
A349733 | Dog | 2017-09-27 19:09:00 | Allie | Spayed Female |
A352713 | Cat | 2017-04-25 12:25:00 | Gia | Spayed Female |
A349990 | Cat | 2018-02-02 14:18:00 | Spice | Spayed Female |
ANIMAL_OUTS 테이블에서
- Allie의 ID는 ANIMAL_INS에 없으므로, Allie의 데이터는 유실되었습니다
- Gia의 ID는 ANIMAL_INS에 있으므로, Gia의 데이터는 유실되지 않았습니다
- Spice의 ID는 ANIMAL_INS에 없으므로, Spice의 데이터는 유실되었습니다
따라서 SQL문을 실행하면 다음과 같이 나와야 합니다.
ANIMAL_ID | NAME |
A349733 | Allie |
A349990 | Spice |
본 문제는 Kaggle의 "Austin Animal Center Shelter Intakes and Outcomes"에서 제공하는 데이터를 사용하였으며 ODbL의 적용을 받습니다.
문제는 2가지 방식으로 풀 수 있다.
1. NOT EXISTS + EQUI JOIN
2. LEFT OUTER JOIN을 사용
> 1번과 2번 oracle, Mysql 모두 사용 가능
♥ 정답 : NOT EXISTS 와 EQUI JOIN 사용
select o.animal_id, o.name
from animal_outs o
where not exists
( select 'x'
from animal_ins i
where i.animal_id = o.animal_id )
order by o.animal_id asc;
■ NOT EXISTS 문
A 테이블에는 존재하는데, B에는 존재하지 않는 데이터를 출력할 때 사용
- 메인쿼리(A)의 데이터를 먼저 읽고 서브쿼리(B)에 그 데이터가 존재하지 않는지 찾아본다.
■ EQUI JOIN 사용
두 컬럼에 동일한 데이터를 가지는 컬럼이 존재할 때 사용할 수 있는 조인방법
- 두 테이블에서 동일한 데이터를 가지는 컬럼명을 WHERE절에서 연결조건으로 사용
정답 해설
위의 내용을 기반으로 해설해보면,
# 1. MAIN QUERY ( ANIMAL_OUTS )
유실된 동물 데이터를 찾아야 하기 때문에
ANIMAL_OUTS에는 존재하는데, ANIMAL_INS에는 존재하지 않는 동물의 ID와 이름을 출력해야한다.
왜냐하면, ANIAML_OUTS 테이블에는 존재하는데, ANIMAL_INS 테이블에 존재하지 않는 데이터가 유실된 동물 테이터이기 때문이다.
-- SELECT절
출력해야할 이름(ANIMAL_ID)와 이름(NAME)을 입력해주는데,
컬럼을 가져올 테이블 명 혹은 테이블의 별칭을
온점(.)을 사용하여 컬렴과 연결해준다.
-- FROM절
main query로 사용할 테이블명을 기입하고,
컬럼명 앞에 편하게 명시해주기 위해서 별칭을 넣어준다.
-- WHERE절
WHERE에 NOT EXISTS를 문과 함께 서브쿼리를 사용해준다.
-- ORDER BY 절
ANIMAL_ID를 기준으로 ASC하게 정렬해준다.
# 2. SUB QUERY ( ANIMAL_OUTS )
-- SELECT절
< 방법 1 : 서브쿼리 테이블의 컬럼명을 넣어주기 >
서브쿼리의 from절의 테이블이 가지고 있는
컬럼명 중 아무거나 넣어주거나,
< 방법 2 : 싱글쿼테이션으로 둘러싸여진 원하는 값 넣어주기 >
싱글쿼테이션으로 둘러싸여진 원하는 값을 넣어주면 된다.
단, NULL은 제외하고 아무런 값이나 가능하다.
select 'x'
위와 같이 'x'를 넣어주었을 경우 수행되는 원리 설명
ex)
1. main 쿼리에 450이라는 animal_Id가 존재
2. id : 450 을 sub 쿼리도 가지고 있는지 확인하기 위해 서브쿼리에 450이라는 값을 넘김
3. 서브쿼리 내에서 450이라는 값이 존재하지 않으면 x가 출력되면서 main query로 넘김
4. 서브쿼리에 없는 450에 대한 데이터가 출력됨
-- FROM 절
데이터를 가져올 테이블 명(ANIMAL_INS) 입력
-- WHERE 절
ANIMAL_INS 테이블과 ANIMAL_OUTS 테이블을
동일한 데이터를 가진 컬럼명을 연결조건으로 사용해서 JOIN해준다.
♥ 정답 : LEFT OUTER JOIN 사용
select o.animal_id, o.name
from animal_outs o left join animal_ins i
on (i.animal_id = o.animal_id)
where i.animal_id is null
order by o.animal_id asc;
■ LEFT OUTER JOIN
LEFT 테이블의 모든 레코드는 유지하고,
우측 테이블과 일치하는 레코드가 없을 때
왼쪽 테이블의 레코드만 유지고 있음
- 즉 위의 쿼리를 보면 ANIMAL_OUTS 테이블의 모든 레코드를 유지하고,
ANIMAL_INS 테이블에 해당하는 레코드가 없는 경우에도 NULL로 결과를 반환한다.
정답 해설
위의 내용을 기반으로 해설해보면,
-- ON 절
ANIMAL_INS 테이블과 ANIMAL_OUTS 테이블을 동일한 데이터를 가진 컬럼명을 연결조건으로 사용해서 JOIN해준다.
-- WHERE 절
LEFT OUTER JOIN을 사용한 이유를 해석해보면,
ANIMAL_INS 테이블의 ANIMAL_ID 가 ANIMAL_OUTS 테이블에 존재하지 않을 때 NULL 값으로 출력되기 때문이다.
따라서 ANIMAL_INS 테이블의 ANIMAL_ID가 IS NULL 인 데이터만 출력한다는 조건을 넣어주면,
결국 유실된 동물의 데이터를 출력해주게 된다.
유실된 동물의 데이터는 ANIMAL_OUTS 테이블에만 존재하기 때문에 이러한 조건을 사용해주게 된 것이다.
출처 : 프로그래머스 코딩 테스트 연습, https://school.programmers.co.kr/learn/challenges
'SQL 문제 풀기 > 1. 프로그래머스 SQL : 2023.12.17~2024.2.29' 카테고리의 다른 글
<프로그래머스 58> 자동차 대여 기록에서 대여중/대여 가능 여부 구분하기(Lv3.) (2) | 2024.02.12 |
---|---|
<프로그래머스 57> 조건에 맞는 사용자 정보 조회하기(Lv.3) (2) | 2024.02.11 |
<프로그래머스 55> 즐겨찾기가 가장 많은 식당 정보 출력하기(Lv.3) (2) | 2024.02.09 |
<프로그래머스 54>대여 기록이 존재하는 자동차 리스트 구하기(Lv.3) (2) | 2024.02.08 |
<프로그래머스 53> 조건에 맞는 사용자와 총 거래금액 조회하기(Lv.3) (4) | 2024.02.07 |