[코드카타] SQL 112번

양승우·2024년 10월 30일

코드카타

목록 보기
25/58

문제 112번

"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()을 써도 된다)

profile
어제보다 오늘 더

0개의 댓글