목차
1. 문제 설명
2. 정답
1. 문제 설명
https://school.programmers.co.kr/learn/courses/30/lessons/299305
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
이 문제의 핵심은 자식이 없는 대장균 또한 출력에 포함시켜야 한다는 것이다.
1. ECOLI_DATA 테이블을 하나는 자식, 하나는 부모라는 이름을 붙여 조인
2. 그룹화
3. 집계 함수 써서 출력
과정을 떠올리긴 했는데 집계 함수 어떻게 써야 될지 뇌정지 와서... 쓸데없이 어렵게 풀었다.
자식이 있는 테이블과 자식이 없는 테이블에서 각자 ID와 자식 개수를 구하고 그 결과를 UNION 하여 결과를 얻었다.
자식이 있는 테이블의 결과는 쉽게 구할 수 있지만 자식이 없는 테이블의 결과를 구하기 위해 어떤 조건을 쓸지 고민하다가
PARENT_ID로 존재하지 않는 ID는 자식이 없다는 조건을 활용했다.
이때 NOT EXISTS와 NOT IN 중 어떤 걸 써주어야 하는지 고민했기에 이에 대한 내용을 잠시 적어보려한다.
NOT EXISTS와 NOT IN은 SQL 서브쿼리에서 자주 사용되는 연산자이나 약간의 차이가 있다.
1. NOT EXISTS
동작방식 | |
서브쿼리에 해당하는 레코드가 존재하지 않으면 TRUE, 존재하면 FALSE를 반환 | |
조건을 만족하는 첫 번째 레코드를 찾으면 즉시 종료 |
▼ 예제
SELECT *
FROM employees e
WHERE NOT EXISTS (
SELECT 1
FROM retired_employees r
WHERE e.emp_id = r.emp_id
);
- employees 테이블에서 retired_employees에 존재하지 않는 직원만 조회함.
- retired_employees에서 emp_id가 매칭되는 첫 번째 값만 확인하고 바로 종료됨.
EXISTS와 NOT EXISTS는 서브쿼리가 결과를 반환하는지 여부만 확인하는 연산자이기 때문에 단순히 "레코드가 존재하는지"만 확인한다.
-- 이런 방식으로 사용 불가
where id not exists (select id from employess)
2. NOT IN
동작방식 | |
서브쿼리의 결과 목록에서 일치하는 값이 없을 경우 TRUE를 반환 | |
모든 서브쿼리 결과를 메모리에 로드한 후 비교하기 때문에 성능 부담이 있음 |
▼ 예제
SELECT *
FROM employees
WHERE emp_id NOT IN (
SELECT emp_id
FROM retired_employees
);
- employees에서 retired_employees의 emp_id 목록에 없는 직원만 조회함.
- 서브쿼리 결과 전체를 한 번에 가져와 비교하므로 데이터가 많을 경우 비효율적일 수 있음.
단 NULL인 값이 있으면 결과가 무조건 FALSE로 연산 자체가 무효화
→ 결과적으로 데이터가 아예 안나올 수도 있음
🚨🚨🚨🚨 따라서 NULL인 값을 제외해주어야 함 !!!!!!!!!!! 🚨🚨🚨🚨
▼ 예제
SELECT *
FROM employees
WHERE id NOT IN (
SELECT id FROM retired_employees WHERE id IS NOT NULL
);
비교 항목 | NOT EXISTS | NOT IN |
동작 방식 | 서브 쿼리가 존재하는지 확인하고 즉시 종료 | 서브쿼리의 전체 결과를 가져와 비교 |
NULL 처리 | NULL 값이 있어도 정상 동작 | NULL 값이 있으면 결과가 무조건 FALSE |
성능 | 인덱스 활용 가능, 최적화 쉬움 | 전체 데이터 로드로 비효율적 |
대상 테이블 크기 | 크기가 클수록 유리 | 크기가 작을 때만 적절 |
2. 정답
(
SELECT PARENT.ID AS ID, COUNT(*) AS CHILD_COUNT
FROM ECOLI_DATA PARENT JOIN ECOLI_DATA CHILD
ON PARENT.ID = CHILD.PARENT_ID
GROUP BY PARENT.ID
)
UNION
(
SELECT ID, COUNT(*) - 1 AS CHILD_COUNT
FROM ECOLI_DATA
WHERE ID NOT IN (SELECT PARENT_ID AS ID FROM ECOLI_DATA WHERE PARENT_ID IS NOT NULL)
GROUP BY ID
)
ORDER BY ID ASC;
자식이 있는 결과와 자식이 없는 결과를 각각 구해 합친 쿼리지만, 과하게 복잡한 듯 하여 다른 사람의 풀이를 봤다.
select a.id, count(b.parent_id) as child_count
from ecoli_data as a
left join ecoli_data as b
on a.id = b.parent_id -- a가 부모 b가 자식
group by a.id;
처음 생각했던 풀이 방식으로 집계 함수로 parent.id를 넣어주고 있다.
parent_id에 NULL이 들어가는 경우는 포함되지 않음에 주의해야 한다.
SUM, AVG, COUNT(COLUMN) 의 경우 NULL인 결과는 무시하지만 COUNT(*)는 NULL인 결과도 포함하여 계산된다.
'Problem Solving > Programmers' 카테고리의 다른 글
[SQL] 멸종위기의 대장균 찾기 문제 풀이 (0) | 2025.03.07 |
---|---|
[SQL] 특정 형질을 가지는 대장균 찾기 문제 풀이 (1) | 2025.03.04 |