SQL/문제풀이

[HackerRank] Weather Observation Station 20 / MySQL로 medium 구하기

응엉잉 2024. 5. 10. 15:12

https://www.hackerrank.com/challenges/weather-observation-station-20/problem?isFullScreen=true

 

Weather Observation Station 20 | HackerRank

Query the median of Northern Latitudes in STATION and round to 4 decimal places.

www.hackerrank.com

쉽게 풀릴줄 알았는데 못풀었다 ...

중앙값을 구현하는 문제

https://chaemi720.tistory.com/350

 

[해커랭크] Weather Observation Station 20 - MySQL

https://www.hackerrank.com/challenges/weather-observation-station-20/problem?isFullScreen=true Weather Observation Station 20 | HackerRank Query the median of Northern Latitudes in STATION and round to 4 decimal places. www.hackerrank.com 문제 LAT_N의

chaemi720.tistory.com

이분의 블로그를 참고해서 쿼리를 작성했다.

 

중앙값은 데이터의 갯수에 따라 구하는 법이 달라지는데

데이터가 짝수개인 경우 

ex. 데이터가 1, 2, 3, 4 총 4개인 경우 --> 중앙값은 (2+3)/2 

일반화하면 전체 데이터가 n개인 경우 --> 중앙값은  n/2 번째, (n/2 + 1) 번째 숫자 2개를 더해서 2로 나눈 값

데이터가 홀수개인 경우

ex. 데이터가 1, 2, 3 --> 중앙값은 2

일반화하면 전체 데이터가 n개인 경우 --> 중앙값은 n + 1 / 2 번째에 있음

 

따라서 중앙값을 구하기 위해서는 전체 데이터 수가 필요하다 !

 

SELECT ROUND(AVG(lat_n), 4)
FROM (SELECT ROW_NUMBER() OVER (ORDER BY lat_n) row_num,
    COUNT(*) OVER () n, 
    lat_n
FROM station) sub
WHERE CASE
    WHEN n %2 = 1 THEN row_num = (n+1)/2
    ELSE row_num IN (n/2, (n/2) + 1) END

 

 

1. 몇번째 데이터인지 알려줄 수 있는 column, 전체 데이터의 갯수를 알려줄 수 있는 column, 데이터를 볼 수 있는 column이 필요하다.

SELECT ROW_NUMBER() OVER (ORDER BY lat_n) row_num, -- 몇번째 데이터인지
	COUNT(*) OVER () n, -- 전체 데이터의 수
    lat_n
FROM station

이때 COUNT() 집계함수를 사용하기 위해 window function을 사용했다.

 

--> 모든 row에 집계값 column을 더해주고 싶은 경우 window function을 사용할 수 있다

 

2. 1번 쿼리를 FROM절 서브쿼리에 넣고 table처럼 활용한다.

전체 데이터의 수가 홀수개인지 짝수개인지에 따라서 출력이 달라저야 하므로 WHERE절에 CASE문을 이용해서 경우를 나누어준다.

SELECT *
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY lat_n) row_num, -- 몇번째 데이터인지
        COUNT(*) OVER () n, -- 전체 데이터의 수
        lat_n
    FROM station
) sub
WHERE
	CASE WHEN n % 2 = 1 THEN row_num = (n+1) / 2 -- 전체 데이터가 홀수개인 경우, row_num이 (n+1) / 2 인 데이터만 거른다
	ELSE row_num IN (n/2, (n/2)+1) END -- 전체 데이터가 짝수개인 경우, row_num이 n/2, n/2 + 1 인 데이터만 거른다

 

--> WHERE절에도 CASE문을 사용할 수 있다. WHERE절은 데이터를 필터링해주는 역할을 한다!

ex. n을 2로 나누었을때 나머지가 1인 경우 --> row_num이 (n+1) / 2 인 row만 필터링한다

==> CASE WHEN n % 2 = 1 THEN row_num = (n+1) / 2

 

3. 문제에서 출력을 원하는 형태는 lat_n의 중앙값을 4자리수에서 반올림한 것이므로, 원하는 형태로 출력되게 만든다

SELECT ROUND(SUM(lat_n), 4)
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY lat_n) row_num, -- 몇번째 데이터인지
        COUNT(*) OVER () n, -- 전체 데이터의 수
        lat_n
    FROM station
) sub
WHERE
	CASE WHEN n % 2 = 1 THEN row_num = (n+1) / 2 -- 전체 데이터가 홀수개인 경우, row_num이 (n+1) / 2 인 데이터만 거른다
	ELSE row_num IN (n/2, (n/2)+1) END -- 전체 데이터가 짝수개인 경우, row_num이 n/2, n/2 + 1 인 데이터만 거른다