https://school.programmers.co.kr/learn/courses/30/lessons/301649
대장균 개체의 크기를 기준으로 분류를 나누는 문제입니다. 군집의 크기가 큰 순서대로 상위 25%는 'CRITICAL', 26%~50%는 'HIGH', 51%~75%는 'MEDIUM', 76%~100%는 'LOW'로 이름을 붙여 출력해야 합니다.
ECOLI_DATA 테이블에는 각 개체의 ID와 크기 정보가 담겨 있습니다.| Column name | Type | Nullable |
|---|---|---|
| ID | INTEGER | FALSE |
| PARENT_ID | INTEGER | TRUE |
| SIZE_OF_COLONY | INTEGER | FALSE |
| DIFFERENTIATION_DATE | DATE | FALSE |
| GENOTYPE | INTEGER | FALSE |
대장균 개체별로 크기 순위에 따른 등급(COLONY_NAME)을 부여하여 출력합니다.
ID, COLONY_NAMEID 오름차순PERCENT_RANK() 함수를 사용하면 (현재 행의 순위 - 1) / (전체 행 수 - 1) 공식을 통해 백분율 위치를 구할 수 있습니다.SIZE_OF_COLONY를 DESC(내림차순)로 정렬하여 크기가 가장 큰 개체가 0(상위 0%)에 가깝게 나오도록 설정합니다.PER)을 조건문에 따라 분기합니다.0.00 <= PER <= 0.25: CRITICAL0.25 < PER <= 0.50: HIGH0.50 < PER <= 0.75: MEDIUM0.75 < PER <= 1.00: LOWID를 기준으로 오름차순 정렬합니다.👉 핵심 아이디어 한 줄 요약
PERCENT_RANK를 사용하여 개체 크기별 상대적 위치를 구하고, 이를 CASE 문으로 4개 등급으로 분류합니다.
SELECT ID,
CASE
WHEN PER <= 0.25 THEN 'CRITICAL'
WHEN PER <= 0.50 THEN 'HIGH'
WHEN PER <= 0.75 THEN 'MEDIUM'
ELSE 'LOW'
END AS COLONY_NAME
FROM (
SELECT ID,
PERCENT_RANK() OVER (ORDER BY SIZE_OF_COLONY DESC) AS PER
FROM ECOLI_DATA
) AS SUB
ORDER BY ID;
-- NTILE을 활용한 대안 풀이
SELECT
ID,
CASE NTILE(4) OVER (ORDER BY SIZE_OF_COLONY DESC)
WHEN 1 THEN 'CRITICAL'
WHEN 2 THEN 'HIGH'
WHEN 3 THEN 'MEDIUM'
WHEN 4 THEN 'LOW'
END AS COLONY_NAME
FROM ECOLI_DATA
ORDER BY ID;
PERCENT_RANK()는 데이터가 0~1 사이의 연속적인 분포를 가질 때 유리합니다. 반면 NTILE(4)를 사용하면 데이터를 강제로 4개의 그룹으로 균등하게 쪼개주므로 코드가 더 간결해질 수 있습니다.PERCENT_RANK()의 결과값을 CASE 문에서 여러 번 비교해야 하므로, 서브쿼리(또는 CTE)를 사용하여 가독성을 높인 점이 아주 좋습니다.이 문제의 핵심인 윈도우 함수(Window Function) 두 가지를 비교 정리합니다.
전체 행에서 현재 행의 상대적 순위 비율을 0~1 사이로 반환합니다.
0.0은 1등, 1.0은 꼴찌를 의미합니다.코드 사용 예시:
SELECT ID,
SIZE_OF_COLONY,
PERCENT_RANK() OVER (ORDER BY SIZE_OF_COLONY DESC) AS PER
FROM ECOLI_DATA;
/* 결과 예시:
ID | SIZE | PER
1 | 1000 | 0.0 (상위 0%)
2 | 500 | 0.5 (상위 50%)
3 | 10 | 1.0 (상위 100%)
*/
데이터를 n개의 그룹으로 균등하게 배분하고 그룹 번호(1~n)를 반환합니다.
NTILE(4)를 쓰면 전체 행이 100개일 때 1~25번까지는 1그룹, 26~50번까지는 2그룹으로 나뉩니다.코드 사용 예시:
SELECT ID,
SIZE_OF_COLONY,
NTILE(4) OVER (ORDER BY SIZE_OF_COLONY DESC) AS QUARTILE
FROM ECOLI_DATA;
/* 결과 예시:
ID | SIZE | QUARTILE
1 | 1000 | 1 (상위 25% 이내)
2 | 800 | 1 (상위 25% 이내)
3 | 500 | 2 (25% ~ 50% 사이)
...
*/
PERCENT_RANK()가 논리적으로 합당합니다.NTILE(n)이 코드의 복잡도를 줄여줍니다.