"Low Salary": All the salaries strictly less than $20000.
"Average Salary": All the salaries in the inclusive range [$20000, $50000].
"High Salary": All the salaries strictly greater than $50000.
The result table must contain all three categories. If there are no accounts in a category, return 0.
(링크)
이 문제의 경우 아이디어가 떠오르지 않아서 고민 시간이 상당히 길었고,
UNION을 사용하라는 힌트를 받은 후에야 풀 수 있었다.
그나마도 방향을 잘못 잡아서 (WITH문으로 LOW-AVERAGE-HIGH가 들어있는 category 컬럼을 먼저 만들고, 여기에 LEFT JOIN을 하는 방식) 코드도 길고 지저분하게 완성되었다
# UNION 사용하여 합하기
WITH make_table AS (
SELECT
distinct 'Low Salary' as 'Category'
FROM
accounts
UNION ALL
SELECT
distinct 'Average Salary' as 'Category'
FROM
accounts
UNION ALL
SELECT
distinct 'High Salary' as 'category'
FROM
accounts
),
# 범위에 맞춰서 count
cnt_case AS (
SELECT
CASE
WHEN income < 20000 THEN 'Low Salary'
WHEN income BETWEEN 20000 AND 50000 THEN 'Average Salary'
ELSE 'High Salary'
END as category
, count(1) as 'cnt'
FROM
accounts
GROUP BY
category
)
SELECT
m.category
, coalesce(c.cnt, 0) as 'accounts_count'
FROM
make_table m
LEFT JOIN cnt_case c
ON m.category = c.category
;
아예 각각 구간에 대해 count를 하는 쿼리 3개를 만들고,
이들을 그대로 UNION ALL로 묶어주면 바로 해결된다
SELECT
'Low Salary' as 'category'
, count(if(income<20000, 1, null)) as 'accounts_count'
FROM
accounts
UNION ALL
SELECT
'Average Salary' as 'category'
, count(if(income BETWEEN 20000 AND 50000, 1, null)) as 'accounts_count'
FROM
accounts
UNION ALL
SELECT
'High Salary' as 'category'
, count(if(income>50000, 1, null)) as 'accounts_count'
FROM
accounts
;
참고로 count()는 0으로 입력 받아도 세기 때문에, 반드시 if문의 False에 대해서는 null을 반환하도록 조건을 걸어주어야 한다
(아니면 True일 때 1, False일 때 0으로 하고 SUM()을 써도 된다)