[프로그래머스/MySQL/JOIN/LV.3] 없어진 기록 찾기

sammy·2024년 6월 26일

SQL 문제풀이

목록 보기
28/87

문제

문제 설명

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_IDANIMAL_INSANIMAL_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의 적용을 받습니다.


✔️  문제접근

LEFT OUTER JOIN 활용

  • LEFT OUTER JOIN을 통해 JOIN 연산 진행 후, ANIMAL_INS 테이블의 특정 컬럼인 ANIMAL_TYPE이 NULL인 조건을 걸어준다.

NOT EXISTS 활용

  • NOT EXISTS (서브쿼리) 형식으로 존재 유무룰 판단한다.

⭐️   내 정답

LEFT OUTER JOIN 활용 풀이

SELECT AO.ANIMAL_ID,AO.NAME
FROM ANIMAL_OUTS AS AO
LEFT OUTER JOIN ANIMAL_INS AS AI
USING (ANIMAL_ID)
WHERE AI.ANIMAL_TYPE IS NULL;

NOT EXISTS 활용 풀이

SELECT ANIMAL_ID, name
FROM ANIMAL_OUTS AO
WHERE NOT EXISTS (
    SELECT 1 FROM ANIMAL_INS WHERE animal_id = AO.animal_id);

🔎  짚고 넘어가기

SELECT 1이란?

SQL에서 SELECT 1을 사용하는 것은 서브쿼리나 특정 조건을 만족하는지를 확인하는 용도로 자주 사용됩니다. 주로 EXISTS 절과 함께 사용되며, 쿼리의 존재 여부를 확인하는데 집중합니다.

1. SELECT 1의 의미

  • SELECT 1은 숫자 1을 선택합니다.
  • 실제로 반환되는 값은 중요하지 않으며, 서브쿼리에서 특정 조건을 만족하는 행이 존재하는지 확인하는 용도로 사용됩니다.

2. 일반적인 사용 예시

A. EXISTS 절과 함께 사용

  • EXISTS는 서브쿼리가 하나 이상의 행을 반환하는지 확인하는 조건문입니다.
  • EXISTS 절 내부에서 SELECT 1을 사용하면, 조건에 맞는 행이 존재하는지만 확인할 수 있습니다.
SELECT *
FROM ANIMAL_INS o
WHERE EXISTS (SELECT 1 FROM ANIMAL_INS WHERE animal_id = o.animal_id);
  • 위 쿼리는 ANIMAL_INS 테이블의 각 행에 대해 동일한 animal_id를 가진 행이 존재하는지 확인합니다. 존재하면 해당 행을 결과로 반환합니다.

3. 효율성 측면

  • SELECT 1은 특정 행이 존재하는지만 확인하기 때문에, 실제로 반환되는 데이터는 중요하지 않습니다.
  • SELECT * 대신 SELECT 1을 사용하면 쿼리가 약간 더 효율적으로 실행될 수 있습니다. 이는 데이터베이스가 실제로 모든 컬럼을 가져올 필요가 없기 때문입니다.

4. SELECT 1의 실제 사용 예시

A. 존재 여부 확인

SELECT CASE 
    WHEN EXISTS (SELECT 1 FROM ANIMAL_INS WHERE animal_id = 'A123')
    THEN 'Exists'
    ELSE 'Does not exist'
END;
  • 이 쿼리는 ANIMAL_INS 테이블에서 animal_id가 'A123'인 행이 존재하는지 확인하고, 존재하면 'Exists', 존재하지 않으면 'Does not exist'를 반환합니다.

B. 조인 없이 중복 확인

SELECT animal_id
FROM ANIMAL_INS o
WHERE EXISTS (SELECT 1 FROM ANIMAL_INS WHERE animal_id = o.animal_id AND condition);
  • 이 쿼리는 ANIMAL_INS 테이블에서 특정 조건을 만족하는 animal_id가 존재하는지 확인하여, 해당 animal_id를 반환합니다.

정리 요약

  • SELECT 1은 서브쿼리에서 행의 존재 여부만을 확인하기 위해 사용됩니다.
  • 주로 EXISTS 절과 함께 사용되며, 불필요한 데이터 조회를 방지하여 쿼리의 효율성을 높입니다.
  • 반환되는 값 자체는 중요하지 않으며, 조건을 만족하는 행이 존재하는지 확인하는 데 중점을 둡니다.
profile
누군가에게 도움을 주기 위한 개발자로 성장하고 싶습니다.

0개의 댓글