[MySQL] GROUP BY 후 조건에 부합하는 값들의 개수 및 비율 구하기
관련 문제: https://leetcode.com/problems/queries-quality-and-percentage/
다음과 같이 query_name 컬럼을 기준으로 GROUP BY 후, rating < 3이라는 특정 조건에 부합하는 값들의 비율을 poor_query_percentage 라는 컬럼으로 반환하려 한다.
1
2
3
4
5
SELECT query_name
, ROUND(AVG(rating / position), 2) AS quality
, <?> AS poor_query_percentage -- <?> 부분을 채워보자!
FROM Queries
GROUP BY query_name
조건에 부합하는 값들의 개수 세기
우선, GROUP BY 후 rating < 3 이라는 조건에 부합하는 값들을 세는 방법에 대해 알아보자.
대표적으로 다음의 세 가지의 방법이 있다.
CASE-WHEN-THEN-(ELSE)-END절과COUNT()사용하기1
COUNT(CASE WHEN rating < 3 THEN 1 END)
IF()와SUM()사용하기1
SUM(IF(rating < 3, 1, 0))
SUM(조건절)사용하기 (→ ✅)조건절 내의 비교 연산자 자체가
0,1값을 반환하므로,COUNT()함수가 필요하지 않다!1
SUM(rating < 3)
조건에 부합하는 값들의 비율 구하기
조건에 부합하는 값들의 비율을 구하기 위해서는 위에서 다룬 방법들로 값들의 개수를 세고 전체 데이터 개수(COUNT(*))로 나누는 방법도 있으나, AVG(조건절)을 사용하면 전체 데이터 개수로 나누지 않아도 된다.
따라서 조건에 부합하는 값들의 비율을 구하는 총 네 가지 방법의 예시를 보면 다음과 같다.
CASE-WHEN-THEN-(ELSE)-END절과COUNT()사용하기1
ROUND(COUNT(CASE WHEN rating < 3 THEN 1 END) / COUNT(*) * 100, 2)
IF()와SUM()사용 후COUNT(*)로 나누기1
ROUND(SUM(IF(rating < 3, 1, 0)) / COUNT(*) * 100, 2)
SUM(조건절)사용 후COUNT(*)로 나누기1
ROUND(SUM(rating < 3) / COUNT(*) * 100, 2)
AVG(조건절)사용하기 (→ ✅)COUNT(*)로 나눌 필요가 없으므로 코드가 가장 간단해진다!1
ROUND(AVG(rating < 3) * 100, 2)
가장 간단한 정답 코드
마지막 방법을 사용하면 다음과 같이 답안을 작성할 수 있다.
1
2
3
4
5
SELECT query_name
, ROUND(AVG(rating / position), 2) AS quality
, ROUND(AVG(rating < 3) * 100, 2) AS poor_query_percentage -- AVG(조건절) 사용
FROM Queries
GROUP BY query_name
정리하면,
IF()나CASE-WHEN-THEN-(ELSE)-END절로 조건을 걸 수도 있으나, 비교연산자 자체가 0, 1 값을 반환하므로 그대로SUM,AVG연산을 이용해도 된다.