프로그래머스 Sql 고득점 Kit Join 문제

없어진 기록 찾기 PGs#59042

코드 보기
SELECT ANIMAL_ID, NAME
FROM ANIMAL_OUTS
WHERE ANIMAL_ID NOT IN (SELECT ANIMAL_ID
                        FROM ANIMAL_INS);
                        
// JOIN 미사용↑ ↓JOIN 사용

SELECT O.ANIMAL_ID, O.NAME
FROM ANIMAL_INS AS I
    RIGHT OUTER JOIN ANIMAL_OUTS AS O
    ON I.ANIMAL_ID = O.ANIMAL_ID 
WHERE SEX_UPON_INTAKE IS NULL AND SEX_UPON_OUTCOME IS NOT NULL

☝ 입력 형식

  • 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는 각각 동물의 아이디, 생물 종, 입양일, 이름, 성별 및 중성화 여부를 나타냅니다.
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문을 작성해주세요.

🤟 구현 과정

JOIN 미사용

  1. 동물의 정보중 동물의 ID, 이름을 요구하므로, SELECT ANIMAL_ID, NAME를 사용하였다.
  2. ANIMAL_OUTS라는 테이블에 있는 정보를 비교하고자 하므로, FROM ANIMAL_OUTS를 사용하였다.
  3. ANIMAL_OUTS에 ID가 있으면서 ANIMAL_INS에는 ID가 없는 경우를 검색하고 싶으므로, Subquery를 이용하여 WHERE ANIMAL_ID NOT IN (SELECT ANIMAL_ID FROM ANIMAL_INS)를 사용해주었다.

JOIN 사용

  1. 동물의 정보중 동물의 ID, 이름을 요구하므로, SELECT O.ANIMAL_ID, O.NAME를 사용하였다. ANIMAL_INS에 없는 데이터를 사용하므로, SELECT I.ANIMAL_ID, I.NAME를 사용하거나, 섞어서 쓰면 안된다.
  2. ANIMAL_OUTSANIMAL_INSANIMAL_ID를 이용해 RIGHT OUTER JOIN시켜 아래의 정보들을 attribute로 갖는 table을 만든다.
    • 자주 두 테이블을 호출해야하므로, 코드의 가독성을 위해 ANIMAL_INS AS I, ANIMAL_OUTS AS O로 수정해주었다.

| ANIMAL_ID | ANIMAL_TYPE | DATETIME | INTAKE_CONDITION | NAME | SEX_UPON_INTAKE | ANIMAL_ID | ANIMAL_TYPE | DATETIME | NAME | SEX_UPON_OUTCOME | |———–|————-|———-|——————|——|—————–|———–|————-|———-|——|——————|

  1. 보호소로 들어온 기록은 없으며, 나간 기록은 없다면 SEX_UPON_INTAKEIS NULL일 것이고, SEX_UPON_OUTCOMEIS NOT NULL이어야 한다. 그러므로, WHERE SEX_UPON_INTAKE IS NULL AND SEX_UPON_OUTCOME IS NOT NULL을 사용하였다.

🍀 Pain Points

JOIN 문제라서 나름대로 JOIN을 사용해서 풀어보고자 했는데, 오히려 끔찍한 SQL문이 탄생했다.

내가 SQL을 잘 못 다뤄서 그런건가?

이 문제는 JOIN을 사용하지 않은 SQL문이 훨신 깔끔하고, 직관적으로 느껴진다.



있었는데요 없었습니다 PGs#59043

코드 보기
SELECT I.ANIMAL_ID, I.NAME
FROM ANIMAL_INS AS I, ANIMAL_OUTS AS O
WHERE I.DATETIME > O.DATETIME AND I.ANIMAL_ID = O.ANIMAL_ID
ORDER BY I.DATETIME
                      
// JOIN 미사용↑ ↓JOIN 사용

SELECT I.ANIMAL_ID, I.NAME
FROM ANIMAL_INS AS I
    JOIN ANIMAL_OUTS AS O
    ON I.ANIMAL_ID = O.ANIMAL_ID 
WHERE I.DATETIME > O.DATETIME
ORDER BY I.DATETIME

☝ 입력 형식

  • 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는 각각 동물의 아이디, 생물 종, 입양일, 이름, 성별 및 중성화 여부를 나타냅니다.
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문을 작성해주세요.
  • 이때 결과는 보호 시작일이 빠른 순으로 조회해야합니다.

🤟 구현 과정

JOIN 미사용

  1. 동물의 정보중 동물의 ID, 이름을 요구하므로, SELECT I.ANIMAL_ID, I.NAME를 사용하였다. SELECT O.ANIMAL_ID, O.NAME를 사용해도, 섞어서 써도 문제 없다.
  2. ANIMAL_INS, ANIMAL_OUTS 두 테이블에 있는 정보를 모두 사용해야 하므로, ANIMAL_INS, ANIMAL_OUTS를 사용하였다.
    • 자주 두 테이블을 호출해야하므로, 코드의 가독성을 위해 ANIMAL_INS AS I, ANIMAL_OUTS AS O로 수정해주었다.
  3. 보호 시작일보다 입양일이 더 빠른 경우를 찾고 싶으므로,ANIMAL_OUTSDATETIME입양일ANIMAL_INSDATETIME보호 시작일보다 더 작야아 한다. 그러므로, WHERE I.DATETIME > O.DATETIME AND I.ANIMAL_ID = O.ANIMAL_ID을 사용하였다.
  4. 동물의 보호 시작일이 빠른 순으로 검색하므로 ORDER BY I.DATETIME를 사용하였다.

JOIN 사용

  1. 동물의 정보중 동물의 ID, 이름을 요구하므로, SELECT I.ANIMAL_ID, I.NAME를 사용하였다. SELECT O.ANIMAL_ID, O.NAME를 사용해도, 섞어서 써도 문제 없다.
  2. ANIMAL_INSANIMAL_OUTSANIMAL_ID를 이용해 JOIN시켜 아래의 정보들을 attribute로 갖는 table을 만든다.
    • 자주 두 테이블을 호출해야하므로, 코드의 가독성을 위해 ANIMAL_INS AS I, ANIMAL_OUTS AS O로 수정해주었다.

| ANIMAL_ID | ANIMAL_TYPE | DATETIME | INTAKE_CONDITION | NAME | SEX_UPON_INTAKE | ANIMAL_ID | ANIMAL_TYPE | DATETIME | NAME | SEX_UPON_OUTCOME | |———–|————-|———-|——————|——|—————–|———–|————-|———-|——|——————|

  1. 보호 시작일보다 입양일이 더 빠른 경우를 찾고 싶으므로,ANIMAL_OUTSDATETIME입양일ANIMAL_INSDATETIME보호 시작일보다 더 작야아 한다. 그러므로, WHERE I.DATETIME > O.DATETIME을 사용하였다.
  2. 동물의 보호 시작일이 빠른 순으로 검색하므로 ORDER BY I.DATETIME를 사용하였다.


오랜 기간 보호한 동물 (1) PGs#59044

코드 보기
SELECT I.NAME, I.DATETIME
FROM ANIMAL_INS AS I
    LEFT OUTER JOIN ANIMAL_OUTS AS O
    ON I.ANIMAL_ID = O.ANIMAL_ID
WHERE SEX_UPON_OUTCOME IS NULL
ORDER BY I.DATETIME
LIMIT 3

☝ 입력 형식

  • 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는 각각 동물의 아이디, 생물 종, 입양일, 이름, 성별 및 중성화 여부를 나타냅니다.
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

🤞 출력 형식

  • 아직 입양을 못 간 동물 중, 가장 오래 보호소에 있었던 동물 3마리의 이름과 보호 시작일을 조회하는 SQL문을 작성해주세요.
  • 결과는 보호 시작일 순으로 조회해야 합니다.

🤟 구현 과정

  1. 동물의 정보중 동물의 ID, 이름을 요구하므로, SELECT I.ANIMAL_ID, I.NAME를 사용하였다. ANIMAL_OUTS에 없는 데이터를 사용하므로, SELECT O.ANIMAL_ID, O.NAME를 사용하거나 섞어서 쓰면 안된다.
  2. ANIMAL_INSANIMAL_OUTSANIMAL_ID를 이용해 JOIN시켜 아래의 정보들을 attribute로 갖는 table을 만든다.
    • 자주 두 테이블을 호출해야하므로, 코드의 가독성을 위해 ANIMAL_INS AS I, ANIMAL_OUTS AS O로 수정해주었다.

| ANIMAL_ID | ANIMAL_TYPE | DATETIME | INTAKE_CONDITION | NAME | SEX_UPON_INTAKE | ANIMAL_ID | ANIMAL_TYPE | DATETIME | NAME | SEX_UPON_OUTCOME | |———–|————-|———-|——————|——|—————–|———–|————-|———-|——|——————|

  1. 아직 입양을 못 간 동물들 중에서 검색해야하므로, WHERE SEX_UPON_OUTCOME IS NULL을 사용하였다.
  2. 동물의 보호 시작일이 빠를 수록 오래 보호한 동물이므로, ORDER BY I.DATETIME를 사용하였다.
  3. 동물 3마리만 검색하므로, LIMIT 3를 사용하였다.


보호소에서 중성화 한 동물 PGs#59045

코드 보기
SELECT I.ANIMAL_ID, I.ANIMAL_TYPE, I.NAME
FROM ANIMAL_INS AS I
    JOIN ANIMAL_OUTS AS O
    ON I.ANIMAL_ID = O.ANIMAL_ID
WHERE I.SEX_UPON_INTAKE LIKE "Intact %" 
    AND O.SEX_UPON_OUTCOME NOT LIKE "Intact %" 
ORDER BY I.ANIMAL_ID

☝ 입력 형식

  • 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는 각각 동물의 아이디, 생물 종, 입양일, 이름, 성별 및 중성화 여부를 나타냅니다.
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 문을 작성해주세요.
  • 중성화를 거치지 않은 동물은 성별 및 중성화 여부에 Intact, 중성화를 거친 동물은 Spayed 또는 Neutered라고 표시되어있습니다.

🤟 구현 과정

  1. 동물의 정보중 동물의 ID, 이름을 요구하므로, SELECT I.ANIMAL_ID, I.ANIMAL_TYPE, I.NAME를 사용하였다. SELECT O.ANIMAL_ID, O.ANIMAL_TYPE, O.NAME를 사용하거나 섞어서 써도 상관없다.
  2. ANIMAL_INSANIMAL_OUTSANIMAL_ID를 이용해 JOIN시켜 아래의 정보들을 attribute로 갖는 table을 만든다.
    • 자주 두 테이블을 호출해야하므로, 코드의 가독성을 위해 ANIMAL_INS AS I, ANIMAL_OUTS AS O로 수정해주었다.

| ANIMAL_ID | ANIMAL_TYPE | DATETIME | INTAKE_CONDITION | NAME | SEX_UPON_INTAKE | ANIMAL_ID | ANIMAL_TYPE | DATETIME | NAME | SEX_UPON_OUTCOME | |———–|————-|———-|——————|——|—————–|———–|————-|———-|——|——————|

3. 1. 보호 시작일에는 중성화 되지 않았어야 하므로, WHERE I.SEX_UPON_INTAKE LIKE "Intact %" 를 사용하였다. 2. 입양일에는 중성화가 되어있어야 하므로, ` AND O.SEX_UPON_OUTCOME NOT LIKE “Intact %” `를 이어서 사용하였다.

  1. 동물의 ID순으로 조회를 해야하므로, ORDER BY I.ANIMAL_ID를 사용하였다.

🍀 Pain Points

1. LIKE

=을 사용하면 뒤에 오는 문장과 데이터가 일치하는 데이터만 검색하지만, LIKE를 사용하면, 뒤에 붙는 오는 문장을 포함하는 데이터를 검색할 수 있다.

댓글남기기