문제 출처 : https://www.hackerrank.com/challenges/weather-observation-station-20/problem?isFullScreen=true
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 4 places.
Input format
The STATION table is described as follows:
LAT_N 의 중앙값을 구하는 문제이다.
MAX,MIN 과 같이 나는 MySQL 에서 중앙값을 구하는 함수도 당연히 제공할 줄 알고 찾아보았지만 그러한 함수는 존재하지 않았다.
따라서 중앙값을 직접 어떻게 구현해야 하는지 한번 알아보았다.
여기서 중앙값이 무엇인지 먼저 짚고 넘어가야, 앞으로 왜 이와같은 쿼리를 작성하는 지 이해할 것 같으니 중앙값이 무엇인지 간략하게 알아보자.
그렇다면 우리는 제공된 테이블을 우선 정렬하고, 가운데에 위치한 값이 무엇인지 찾으면 되는 문제라고 볼 수 있다.
보통 가운데에 위치한 값을 구하기 위해서 전체의 길이를 2로 나눠 가운데를 찾을텐데 이런 원리를 그대로 쿼리에 적용해보자.
우선 LAT_N 을 순서대로 정렬하였을 때 각 행이 몇번째 인지 알아야 나중에 이 값을 가지고 중앙값을 구할 수 있기 때문에 정렬 후 행별 인덱스가 필요할 것 같다.
행별 인덱스를 지정하기 위해 다음과 같이 변수를 선언하고, 선언한 변수를 이용하여 0부터 시작하는 인덱스를 지정해주었다.
SET @rowIndex=-1;
SELECT
@rowIndex:=@rowIndex+1 AS IDX,
LAT_N
FROM
STATION
ORDER BY
LAT_N
MySQL 에서 변수를 사용하기 위해선 SET 이라는 키워드를 이용하여 다음과 같이 선언할 수 있고 이를 쿼리문 내에 사용이 가능하다.
(SET 에 관한 블로그 정리는 추후에 진행하자.)
여기서 이제 전체의 행이 짝수일 때와 홀수일 때 중앙값은 어떻게 구해야 할 지 한번 생각이들만하다.
하나씩 간단한 예를들어 살펴보자.
| index | value |
|---|---|
| 0 | 100 |
| 1 | 200 |
| 2 | 300 |
| 3 | 400 |
먼저 이와같이 짝수개가 있는경우 중앙값은 의 값인 250 이 중앙값에 해당한다.
| index | value |
|---|---|
| 0 | 100 |
| 1 | 200 |
| 2 | 300 |
| 3 | 400 |
| 4 | 500 |
다만 이처럼 홀수개가 있는경우 중앙값은 전체의 중간에 위치한 300 의 값이 중앙값에 해당한다.
이처럼 짝수와 홀수인경우 조금 다른 계산과정을 볼 수 있는데
이 계산과정 때문에 index를 1부터 시작하지 않고, 0부터 시작하였다.
원리는 아주 단순하다 마지막 인덱스의 절반값을 기준으로 내림한 결과와, 마지막 인덱스의 절반값을 기준으로 올림한 결과의 평균값을 구한다면 그게 중앙값이 되는 원리이다.
예를들어 위 짝수의 경우를 살펴보자 마지막인덱스는 3이다 3의 절반은 1.5 이고 여기서 내림한결과는 1 이고, 올림한 결과는 2 이다.
따라서 index 가 1인 값과 2인 값의 평균값을 통해 중앙값을 구할 수 있다.
그렇다면 예를든 홀수개인 테이블을 보면 4의 절반은 2이고 여기서 내림과 올림을해도 2 이고 2에 해당한 값의 평균값이 중앙값이 된다.
이제 이 원리를 이해했다면 그대로 쿼리로 작성하면 된다.
나는 여기서 다음과 같이 서브쿼리를 사용하여 조건에 맞는 테이블 ( 전체행의 가운데에 올 수 있는 행 ) 을 조회하였다.
SET @rowIndex=-1;
SELECT
ROUND(AVG(LAT_N),4) median
FROM
(
SELECT
@rowIndex:=@rowIndex+1 AS IDX,
LAT_N
FROM
STATION
ORDER BY
LAT_N
) b
WHERE IDX IN (FLOOR(@rowIndex / 2), CEIL(@rowIndex / 2))
조회 후 테이블의 평균값을 구하여 중앙값을 위와 같이 구하였다.
이번 문제로 SET 을 통해 변수를 지정하고, 활용하는 방법에 대해 이러한 방법도 있다는 것을 알았다.
또한 매번 쓸때마다 아..올림함수 있었는데, 내림함수 있엇는데... 생각하며 검색하여 사용했었는데 이번 문제를 통해 다시 한번 사용해보며 익힐 수 있는 기회였다.