본문 바로가기

SQL/DataLemar

[PostgreSQL] (Medium) Top 5 Artists [Spotify SQL Interview Question]

문제: https://datalemur.com/questions/top-fans-rank

 

나의 풀이

WITH tb AS (
  SELECT artist_name
      , song_id
      , COUNT(*) AS cnt
  FROM artists a
      JOIN songs s USING (artist_id)
      JOIN global_song_rank g USING (song_id)
  WHERE rank <= 10
  GROUP BY 1, 2)

SELECT *
FROM (
  SELECT artist_name
      , DENSE_RANK() OVER (ORDER BY SUM(cnt) DESC) AS artist_rank
  FROM tb
  GROUP BY 1) sub
WHERE artist_rank <= 5
ORDER BY 2, 1;

 

일단 이렇게 하면 틀림

하지만 디스커션에서 나와 똑같이 생각하는 사람들을 많이 만날 수 있다 ㅋㅅㅋ

 

문제에서 랭크가 같을 경우 아티스트 이름 기준 오름차순 정렬하라고 되어 있는데 

정답에는 같은 랭크에 대해서 B는 D 앞에 오지만(ASC), A는 E 뒤에 옴 (DESC) 

either way doesn't work 그래서 나는 문제가 틀렸다고 생각했는데

정답 코드가 있고 정답처리도 잘 된다.. 

 

1. 이 부분 왜 그런지 정리해야하고

2. 코드 더 간결하게 수정하기~

 

먼저 코드 더 간결하게 나타내는 부분! 나는 카운트랑 덴스 랭크를 따로 적용했는데 

덴스 랭크 안에 카운트를 넣어서 한 번에 표현 가능하다!

다시 보니 왜 그룹바이를 song_id까지 해서 SUM()을 해줬는지 모르겠다 ㅋㅋ

그룹바이를 artist_name까지만 하고 바로 COUNT() 하면 간단하게 끝난다!

SELECT artist_name
     , DENSE_RANK() OVER (ORDER BY COUNT(song_id) DESC)
FROM artists a
     JOIN songs s USING (artist_id)
     JOIN global_song_rank g USING (song_id)
WHERE rank <= 10
GROUP BY 1;

 

요렇게 ㅎㅎ

 

그럼 이제 덴스 랭크가 5순위까지이면서, 중복 랭크에 대해서는 이름 순으로 정렬을 하면 된다.

WITH tb AS (
  SELECT artist_name
       , DENSE_RANK() OVER (ORDER BY COUNT(song_id) DESC) AS artist_rank
  FROM artists a
       JOIN songs s USING (artist_id)
       JOIN global_song_rank g USING (song_id)
  WHERE rank <= 10
  GROUP BY 1)

SELECT *
FROM tb
WHERE artist_rank <= 5;

앞에서 만든 쿼리를 위드문안에 담아주고 이걸 테이블처럼 쓰면서 랭킹 5순위 조건을 주면 된다.

따로 정렬 조건을 주지 않은 지금 쿼리 결과는 랭크가 오름차순으로 되어있고 B가 D 앞에 오면서 E가 A 앞에 오는 정답이랑 일치하는 아웃풋이 나온다. 

 

그러니까 결국 아무 정렬 조건을 주지 않은 것임 쿸스..

 

문제에서 아티스트 이름 순으로 정렬 부분이 수정 되어야할듯..

아무튼 해결!