해커랭크(HackerRank) MySQL, 난이도 MEDIUM 1 문제 풀이


📍 테이블 정보

The STATION table is described as follows:

Field Type
ID NUMBER
CITY VARCHAR2(21)
STATE VARCHAR2(2)
LAT_N NUMBER
LONG_W NUMBER

cf. where LAT_N is the northern latitude and LONG_W is the western longitude.


1. Weather Observation Station 20

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 4 decimal places.
Weather Observation Station 20 문제 보러가기

(1) 문제 이해

문제는 LAT_N의 중간값을 구하고 소수점 4자리로 반올림하여 출력하는 것이다.

(2) 코드 작성

SELECT ROUND(AVG(LAT_N), 4)
FROM (SELECT LAT_N
           , ROW_NUMBER() OVER(ORDER BY LAT_N) AS IDX
           , COUNT(*) OVER() + 1 AS CNT
      FROM STATION) AS T
WHERE IDX = CEIL(CNT/2) OR IDX = FLOOR(CNT/2)
위 쿼리의 실행 결과


(3) 코드 리뷰

  • 오라클에선 중앙값을 구하는 함수를 제공하지만 MySQL은 지원하지 않는다.
  • 직접 중앙값을 구해야하는데 방법을 모르겠어서 풀이법을 참고해서 문제를 해결했다.
  • 전체 행들 중에서 LAT_N을 기준으로 순서를 나열하기 위해 ROW_NUMBER 함수를 사용했다. 그리고 전체 행의 수를 구하기 위해 COUNT 함수와 OVER 함수를 사용했다.
    • OVER 함수는 GROUP BY 없이 집계함수를 사용할 수 있다. 따로 파티션을 나누지 않고 전체 데이터를 카운트하였다.
  • 중앙값 계산 기준은 전체 행의 개수가 짝수일 때, 중앙에 있는 두개의 값의 평균값이고 홀수일 땐 중앙에 있는 하나의 값이다.
  • 중앙값 계산을 위해 전체 행의 수 + 1 로 CNT 에 담았다. 이를 서브쿼리로 불러왔다.
  • WHERE 문에 IDX가 전체 행의 개수를 2로 나눈값 기준 내림, 올림 했을 때의 값과 같은 데이터만 불러올 수 있도록 조건식을 작성했다.
  • 중앙값에 해당하는 행의 평균값을 소수점 4자리 수로 반올림하여 불러오기 위해 AVG, ROUND 함수를 사용했다.

🌞 실패 코드 공유

SELECT ROUND(AVG(LAT_N), 4)
FROM (SELECT LAT_N
           , ROW_NUMBER() OVER(ORDER BY LAT_N) AS IDX
      FROM STATION) AS T
WHERE IDX = CEIL(COUNT(*)/2) OR IDX = FLOOR(COUNT(*)/2)
위 쿼리의 실행 결과


ROW_NUMBER을 사용해서 구해보려고 했으나 총 데이터의 개수(행의 개수)를 구하는 것 때문에 계속 오류가 발생했다. 처음에 다른 풀이법의 도움없이 접근했을 때 아래와 같이 쿼리를 작성했는데 GROUP FUNCTION 을 사용했다는 이유로 에러가 계속 발생했다. 전체 행의 수를 구하는 것에서 계속 문제가 발생했고 이러한 이유로 풀이법을 참고하게 되었다. SET 으로 새로운 변수를 지정하고 COUNT(*) 값을 저장하려고 했으나 집계함수의 사용에 제약이 있어서 사용이 어려웠다. 이번 기회에 GROUP BY 와 GROUP FUNCTION, OVER 함수 간의 관계를 다시 정리해보아야겠다.🔥


2. Reference

👩🏻‍💻개인 공부 기록용 블로그입니다
오류나 틀린 부분이 있을 경우 댓글 혹은 메일로 따끔하게 지적해주시면 감사하겠습니다.

댓글남기기