https://school.programmers.co.kr/learn/courses/30/lessons/301647
대장균 개체 테이블에서 “자식이 부모의 형질(비트마스크)을 모두 포함하는” 개체만 골라 ID, 자식 형질, 부모 형질을 출력하는 문제입니다.
ECOLI_DATA는 대장균 개체의 기본 정보와 유전 형질(GENOTYPE)을 정수 비트마스크로 저장합니다.PARENT_ID가 NULL이면 최초 개체(부모 없음)이며, 그 외에는 부모를 참조합니다.| Column name | Type | Nullable |
|---|---|---|
| ID | INTEGER | FALSE |
| PARENT_ID | INTEGER | TRUE |
| SIZE_OF_COLONY | INTEGER | FALSE |
| DIFFERENTIATION_DATE | DATE | FALSE |
| GENOTYPE | INTEGER | FALSE |
부모의 형질을 모두 보유한 대장균의 정보를 출력합니다.
ID, GENOTYPE, PARENT_GENOTYPE(부모의 GENOTYPE)PARENT_ID IS NOT NULL), 자식이 부모의 형질을 모두 포함해야 함ID 오름차순부모-자식 관계를 Self Join으로 구성합니다.
ECOLI_DATA 테이블을 자식(ED1)과 부모(ED2)로 나누어 생각하고, ED1.PARENT_ID = ED2.ID 조건으로 부모 레코드를 연결합니다.
부모가 없는 개체는 제외합니다.
최초 개체는 PARENT_ID가 NULL이므로 비교 대상이 없어 조건을 판단할 수 없습니다.
따라서 WHERE ED1.PARENT_ID IS NOT NULL로 부모가 존재하는 행만 남깁니다.
비트 연산으로 “부모 형질을 모두 포함” 여부를 판별합니다.
형질은 정수 비트마스크이므로, (ED1.GENOTYPE & ED2.GENOTYPE) = ED2.GENOTYPE이면 부모의 1비트들이 자식에서도 모두 1이라는 뜻입니다.
이 조건을 만족하는 자식만 필터링합니다.
요구 정렬 조건을 적용합니다.
결과는 ORDER BY ED1.ID ASC로 ID 오름차순 정렬합니다.
👉 핵심 아이디어 한 줄 요약
Self Join으로 부모 GENOTYPE을 가져온 뒤, (자식 & 부모) = 부모 조건으로 포함 관계를 검사합니다.
SELECT ED1.ID, ED1.GENOTYPE, ED2.GENOTYPE PARENT_GENOTYPE
FROM ECOLI_DATA ED1 LEFT JOIN ECOLI_DATA ED2
ON ED1.PARENT_ID = ED2.ID
WHERE ED1.PARENT_ID IS NOT NULL
AND (ED1.GENOTYPE & ED2.GENOTYPE = ED2.GENOTYPE)
ORDER BY ED1.ID ASC;
SELECT
C.ID,
C.GENOTYPE,
P.GENOTYPE AS PARENT_GENOTYPE
FROM ECOLI_DATA C
JOIN ECOLI_DATA P
ON C.PARENT_ID = P.ID
WHERE (C.GENOTYPE & P.GENOTYPE) = P.GENOTYPE
ORDER BY C.ID ASC;
LEFT JOIN을 쓰고 WHERE C.PARENT_ID IS NOT NULL로 거르는 방식은, 논리적으로 INNER JOIN과 동일한 결과가 되므로 JOIN이 더 의도가 명확합니다. (부모가 반드시 있어야 하니까요.)C.GENOTYPE & P.GENOTYPE = P.GENOTYPE처럼 써도 동작하는 DB가 많지만, 가독성과 우선순위 오해 방지를 위해 (C.GENOTYPE & P.GENOTYPE) = P.GENOTYPE처럼 괄호를 권장합니다.ED1/ED2 대신 C/P(Child/Parent)로 두면 더 빨리 이해하기 좋습니다.(자식 & 부모) = 부모로 표현합니다.PARENT_ID IS NULL)은 조인 자체가 성립하지 않으므로, 이 문제에선 JOIN이 자연스럽습니다.