먼지뭉치 Data Analysis

[HackerRank] Weather Observation Station20: Median(중앙값) 구하기 본문

SQL

[HackerRank] Weather Observation Station20: Median(중앙값) 구하기

데이터분석과 개발 2025. 3. 23. 15:55

안녕하세요 오늘도 계속해서 HackerRank 문제를 정리해보도록 하겠습니다.

이번에 푼 문제는 Weather Observation Station 20이라는 문제였고요.

결국 Median(중앙값)을 구하는 문제였습니다.

파이썬으로는 간단하게 구할 수 있는 값을 쿼리로 구하려다 보니 상당히 많이 헷갈렸네요.

 

Q. LAT_N 값의 Median 값을 소수점 4째자리까지 반올림하여 나타내시오.

A median is defined as a number separating the higher half of a data set from the lower half. Query the median of the Northern Latitudes (LAT_N) from STATION and round your answer to  decimal places.

Input Format

The STATION table is described as follows:


첫시도.

중앙값의 경우 데이터를 정렬했을 때 가장 가운데 있는 값이므로

전체 행의 개수를 n이라고 할때,

n= 홀수일땐 : y(n/2),

n= 짝수일땐 : y((n/2) - 1), y((n/2) + 1) 의 평균

 

이므로 어떻게 하면 함수값처럼 Lat_n값을 추출할 수 있을 지 고민했고 데이터 정렬로 행 번호가 필요하겠단 생각이 들었습니다.

그리고 전체 행 번호가 필요하겠구나 싶어 윈도우 함수를 사용해 하나의 CTE를 만든 결과입니다.

 

# 첫시도
WITH ORDERED_DATA AS (
    SELECT LAT_N,
        ROW_NUMBER() OVER (ORDER BY LAT_N) AS ROW_NUM,
        COUNT(*) OVER () AS TOTAL_ROWS
    FROM STATION
)
SELECT * FROM ORDERED_DATA

첫 시도..

 

Lat_n 값 오름차순으로 행번호랑 총 행수를 출력하였습니다. 

 

하지만, 특정행의 값을 어떻게 추출하는지를 도저히 모르겠었고 그 다음 단계로 넘어가기 어려웠습니다.


Solution.

(step1) 짝수, 홀수 2가지 경우 한번에 조건 걸어주기

 

결국 where 조건 절에 특정 행 번호를 넣어줘야 하는 것이지만

홀수일 땐 y(n/2), 짝수일 땐 y((n/2) - 1), y((n/2) + 1)를 한번에 표현하는 부분이 어려웠습니다.

홀수일땐 값이 1개, 짝수일땐 2개가 나와야 하니.. 막막했네요.

WITH ORDERED_DATA AS (
    SELECT LAT_N,
        ROW_NUMBER() OVER (ORDER BY LAT_N) AS ROW_NUM,
        COUNT(*) OVER () AS TOTAL_ROWS
    FROM STATION
),
MEDIAN_CALC AS (
    SELECT LAT_N,
            TOTAL_ROWS,
            ROW_NUM
    FROM ORDERED_DATA
    WHERE ROW_NUM = FLOOR((TOTAL_ROWS+1)/2)
        OR ROW_NUM = CEIL((TOTAL_ROWS+1)/2)
    )

 

WHERE ROW_NUM = FLOOR((TOTAL_ROWS+1)/2)
        OR ROW_NUM = CEIL((TOTAL_ROWS+1)/2)

 

where절에 or을 써서 2가지 값이지만 홀수일 땐 2개의 값이 같아서 1개의 값이, 짝수일 땐 2개의 값이 나오게 됩니다.

하나의 스킬적인 부분인 것 같네요. 

 

(step2) 짝수, 홀수일 때 case when으로 median값 구하기

#전체 정답 쿼리
WITH ORDERED_DATA AS (
    SELECT LAT_N,
        ROW_NUMBER() OVER (ORDER BY LAT_N) AS ROW_NUM,
        COUNT(*) OVER () AS TOTAL_ROWS
    FROM STATION
),
MEDIAN_CALC AS (
    SELECT LAT_N,
            TOTAL_ROWS,
            ROW_NUM
    FROM ORDERED_DATA
    WHERE ROW_NUM = FLOOR((TOTAL_ROWS+1)/2)
        OR ROW_NUM = CEIL((TOTAL_ROWS+1)/2)
    )

SELECT 
    CASE
        WHEN MAX(TOTAL_ROWS)%2=1 THEN ROUND(MAX(LAT_N),4)
        ELSE ROUND(AVG(LAT_N),4)
    END AS MEDIAN_VALUE
FROM MEDIAN_CALC;

 

 

case when으로 행의 전체 개수가 짝수일때, 홀수일때를 나눠 median을 계산해준 쿼리입니다.

파이썬과 다르게 total_row%2 == 1이 아닌, sql은 total_row%2 = 1 이라는 점 주의해주시면 좋을 것 같습니다.

 

 

* CTE를 2개를 만들면 된다는 점

* 짝수, 홀수 일때 where절 스킬적인 부분

 

등등을 알게 된 것 같습니다.

 

계속해서 sql문제들을 정리해보도록 하겠습니다. 감사합니다!