프로그래머스 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 미사용
- 동물의 정보중 동물의 ID, 이름을 요구하므로,
SELECT ANIMAL_ID, NAME를 사용하였다. ANIMAL_OUTS라는 테이블에 있는 정보를 비교하고자 하므로,FROM ANIMAL_OUTS를 사용하였다.ANIMAL_OUTS에 ID가 있으면서ANIMAL_INS에는 ID가 없는 경우를 검색하고 싶으므로, Subquery를 이용하여WHERE ANIMAL_ID NOT IN (SELECT ANIMAL_ID FROM ANIMAL_INS)를 사용해주었다.
JOIN 사용
- 동물의 정보중 동물의 ID, 이름을 요구하므로,
SELECT O.ANIMAL_ID, O.NAME를 사용하였다.ANIMAL_INS에 없는 데이터를 사용하므로,SELECT I.ANIMAL_ID, I.NAME를 사용하거나, 섞어서 쓰면 안된다. ANIMAL_OUTS에ANIMAL_INS를ANIMAL_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 | |———–|————-|———-|——————|——|—————–|———–|————-|———-|——|——————|
- 보호소로 들어온 기록은 없으며, 나간 기록은 없다면
SEX_UPON_INTAKE는IS NULL일 것이고,SEX_UPON_OUTCOME은IS 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 미사용
- 동물의 정보중 동물의 ID, 이름을 요구하므로,
SELECT I.ANIMAL_ID, I.NAME를 사용하였다.SELECT O.ANIMAL_ID, O.NAME를 사용해도, 섞어서 써도 문제 없다. ANIMAL_INS,ANIMAL_OUTS두 테이블에 있는 정보를 모두 사용해야 하므로,ANIMAL_INS, ANIMAL_OUTS를 사용하였다.- 자주 두 테이블을 호출해야하므로, 코드의 가독성을 위해
ANIMAL_INS AS I, ANIMAL_OUTS AS O로 수정해주었다.
- 자주 두 테이블을 호출해야하므로, 코드의 가독성을 위해
- 보호 시작일보다 입양일이 더 빠른 경우를 찾고 싶으므로,
ANIMAL_OUTS의DATETIME입양일이ANIMAL_INS의DATETIME보호 시작일보다 더 작야아 한다. 그러므로,WHERE I.DATETIME > O.DATETIME AND I.ANIMAL_ID = O.ANIMAL_ID을 사용하였다. - 동물의 보호 시작일이 빠른 순으로 검색하므로
ORDER BY I.DATETIME를 사용하였다.
JOIN 사용
- 동물의 정보중 동물의 ID, 이름을 요구하므로,
SELECT I.ANIMAL_ID, I.NAME를 사용하였다.SELECT O.ANIMAL_ID, O.NAME를 사용해도, 섞어서 써도 문제 없다. ANIMAL_INS에ANIMAL_OUTS를ANIMAL_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 | |———–|————-|———-|——————|——|—————–|———–|————-|———-|——|——————|
- 보호 시작일보다 입양일이 더 빠른 경우를 찾고 싶으므로,
ANIMAL_OUTS의DATETIME입양일이ANIMAL_INS의DATETIME보호 시작일보다 더 작야아 한다. 그러므로,WHERE I.DATETIME > O.DATETIME을 사용하였다. - 동물의 보호 시작일이 빠른 순으로 검색하므로
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문을 작성해주세요.
- 결과는 보호 시작일 순으로 조회해야 합니다.
🤟 구현 과정
- 동물의 정보중 동물의 ID, 이름을 요구하므로,
SELECT I.ANIMAL_ID, I.NAME를 사용하였다.ANIMAL_OUTS에 없는 데이터를 사용하므로,SELECT O.ANIMAL_ID, O.NAME를 사용하거나 섞어서 쓰면 안된다. ANIMAL_INS에ANIMAL_OUTS를ANIMAL_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 | |———–|————-|———-|——————|——|—————–|———–|————-|———-|——|——————|
- 아직 입양을 못 간 동물들 중에서 검색해야하므로,
WHERE SEX_UPON_OUTCOME IS NULL을 사용하였다. - 동물의 보호 시작일이 빠를 수록 오래 보호한 동물이므로,
ORDER BY I.DATETIME를 사용하였다. - 동물 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라고 표시되어있습니다.
🤟 구현 과정
- 동물의 정보중 동물의 ID, 이름을 요구하므로,
SELECT I.ANIMAL_ID, I.ANIMAL_TYPE, I.NAME를 사용하였다.SELECT O.ANIMAL_ID, O.ANIMAL_TYPE, O.NAME를 사용하거나 섞어서 써도 상관없다. ANIMAL_INS에ANIMAL_OUTS를ANIMAL_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 %” `를 이어서 사용하였다.
- 동물의 ID순으로 조회를 해야하므로,
ORDER BY I.ANIMAL_ID를 사용하였다.
🍀 Pain Points
1. LIKE
=을 사용하면 뒤에 오는 문장과 데이터가 일치하는 데이터만 검색하지만, LIKE를 사용하면, 뒤에 붙는 오는 문장을 포함하는 데이터를 검색할 수 있다.
댓글남기기