인프런 커뮤니티 질문&답변

Idea님의 프로필 이미지
Idea

작성한 질문수

[백문이불여일타] 데이터 분석을 위한 중급 SQL

LeetCode CASE문 WHEN절을 사용한 1179번 문제 질문입니다.

작성

·

898

12

안녕하세요.

LeetCode 1179번 문제에서 헷갈리는 부분이 있어서 질문 드립니다.

우선 답안 해설 코드는 다음과 같다고 강의에서 보았습니다.

SELECT id 

     , SUM(CASE WHEN month = "Jan" THEN revenue ELSE NULL END) as Jan_Revenue

     , SUM(CASE WHEN month = "Feb" THEN revenue ELSE NULL END) as Feb_Revenue

     , SUM(CASE WHEN month = "Mar" THEN revenue ELSE NULL END) as Mar_Revenue

     , SUM(CASE WHEN month = "Apr" THEN revenue ELSE NULL END) as Apr_Revenue

     , SUM(CASE WHEN month = "May" THEN revenue ELSE NULL END) as May_Revenue

     , SUM(CASE WHEN month = "Jun" THEN revenue ELSE NULL END) as Jun_Revenue

     , SUM(CASE WHEN month = "Jul" THEN revenue ELSE NULL END) as Jul_Revenue

     , SUM(CASE WHEN month = "Aug" THEN revenue ELSE NULL END) as Aug_Revenue

     , SUM(CASE WHEN month = "Sep" THEN revenue ELSE NULL END) as Sep_Revenue

     , SUM(CASE WHEN month = "Oct" THEN revenue ELSE NULL END) as Oct_Revenue

     , SUM(CASE WHEN month = "Nov" THEN revenue ELSE NULL END) as Nov_Revenue

     , SUM(CASE WHEN month = "Dec" THEN revenue ELSE NULL END) as Dec_Revenue

FROM department

GROUP BY id

여기서 질문 드립니다. group by id를 수행하면서 select 문 내에 집계함수 SUM을 사용하셨는데, SUM 함수를 왜 사용한건지 잘 이해가 가지 않습니다..(즉, SUM 함수를 사용하지 않고 그냥 group by id 만 사용하면 틀린 답이 나오는데, 이 부분에 대한 설명 좀 부탁드립니다)

구글링을 해보니 group by 는 집계함수와 같이 사용해야 한다고 나와있긴 하던데...잘 이해가 가지 않네요 ㅜㅜ

또한 구글링 예시에서는 SUM 함수 말고 MAX 함수를 사용했던데, 결과는 SUM 함수를 사용했을 때와 동일하게 나오더군요.

이 부분에 대해서 자세히 설명해주시면 감사하겠습니다!

답변 5

23

윤선미님의 프로필 이미지
윤선미
지식공유자

안녕하세요 :)

일단 아래 참고자료를 자세하게 읽어봐주시면 Pivot 을 확실하게 이해하실 수 있을 것 같아요.
https://mode.com/sql-tutorial/sql-pivot-table/

문제에서 주어진 테이블을 기준으로 설명을 한 번 해보겠습니다.
집계함수와, GROUP BY를 제외하고 쿼리를 실행해보고, 그 결과물이 어떻게 나오는지 볼게요.

그룹바이와 집계함수를 빼고,

SELECT id
              , CASE WHEN month='Jan' THEN revenue ELSE NULL END AS Jan_Revenue
              , CASE WHEN month='Feb' THEN revenue ELSE NULL END AS Feb_Revenue
              , CASE WHEN month='Mar' THEN revenue ELSE NULL END AS Mar_Revenue
FROM department

이렇게 쿼리를 작성했다고 생각해봅시다. 그러면 예상되는 결과물은 아래와 같습니다.

| id | Jan_Revenue | Feb_Revenue | Mar_Revenue |
|----|-------------|-------------|-------------|
| 1  | 8000        | null        | null        |
| 2  | 9000        | null        | null        |
| 3  | null        | 10000       | null        |
| 1  | null        | 7000        | null        |
| 1  | null        | null        | 6000        |

기존의 테이블에 Revenue 컬럼에서,
month 조건에 해당되는 값들만 남고 나머지는 null로 바꿔주는 연산을 CASE가 수행했습니다.

혹시 CASE 사용이 명확하게 안 와닿으시면 Pivot 문제풀이 전 강의를 참고해주세요 :)

자, 이제 각 부서별로 데이터를 요약해줘야 하는 차례입니다. 헷갈릴 수 있으니까 Jan_Revenue만 생각해봅시다.

SELECT id
              , SUM(CASE WHEN month='Jan' THEN revenue ELSE NULL END) AS Jan_Revenue
FROM department
GROUP BY id

결과물은 이렇게 나오겠죠?

| id | Jan_Revenue |
|----|-------------|
| 1  | 8000        |
| 2  | 9000        |
| 3  | null        |

여기에서 8000은 저 위에 테이블에서 id=1에 해당하는 SUM([8000, null, null]) 의 결과물입니다.
SUM()이라는 집계함수는 null을 무시하므로 8000이 남았습니다.

질문주신 MAX() 또한 null을 무시하므로 MAX([8000, null, null])의 결과물은 8000이 나오겠지요?

각 부서마다, 매 월 받는 예산은 1번씩만 있으므로 SUM()과, MAX()의 결과물은 같습니다.  AVG(), MIN() 을 사용하셔도 마찬가지입니다. 만약, 각 부서마다 월에 받는 예산이 2번 이상인데, 요약은 월 단위로 해야한다면 SUM(), MAX() 등 집계함수마다 다르게 계산될 수 있으니 그 부분을 주의하셔야겠습니다.

확장해서 부서 1번의 Feb_Revenue는 SUM([null, 7000, null]) 으로 계산 될겁니다.  부서 2, 3번은 데이터가 하나씩밖에 안 들어있어서 계산해볼것도 없겠네요. 연습삼아 가짜 데이터를 넣고 계산 해보시면 좋겠습니다.

이해하는데 도움이 되었으면 좋겠네요.

질문과, 답변을 강의에 링크로 걸고 다른 분들도 공부하시는데 도움이 되도록 할게요.
좋은 질문 해주셔서 감사합니다!

혹시, sum을 쓰지 않고 그냥 group by 만 쓰면

왜 오류가 나는지 더 추가 설명을 받을 수 있을까요ㅠㅠ?

윤선미님의 프로필 이미지
윤선미
지식공유자

learn&learn 님, 안녕하세요 :)

질문에 코드와, 그 코드를 쓰면서 예상했던 결과, 그리고 실제 결과나 에러 값을 함께 주시면
더 좋은 답변을 드릴 수 있을 것 같아요. 질문 등록 부탁드릴게요.

감사합니다!

위에 learn&learn님과 같은 질문을 드리고 싶어요.

부서별로 월별 예산을 요약해야 하므로 GROUP BY를 사용하는 것은 이해가 됩니다.

그러나 1 부서당 월 1회의 예산을 받는다면 id와  각 month_Revenue가 대응되는 값은 어차피 1개인데 왜 SUM을 해주어햐 하는지는 잘 이해가 안가네요.

(말씀하신대로 월 2회 이상 예산을 받는다면 SUM을 쓰는 것은 이해가 됩니다)

SUM을 빼고 코드를 실행하면 아래와 같은 결과가 나오네요.

*코드

SELECT id, CASE WHEN Month = 'Jan' THEN Revenue ELSE NULL END AS Jan_Revenue,

CASE WHEN Month = 'Feb' THEN Revenue ELSE NULL END AS Feb_Revenue,

CASE WHEN Month = 'Mar' THEN Revenue ELSE NULL END AS Mar_Revenue,

CASE WHEN Month = 'Apr' THEN Revenue ELSE NULL END AS Apr_Revenue,

CASE WHEN Month = 'May' THEN Revenue ELSE NULL END AS May_Revenue,

CASE WHEN Month = 'Jun' THEN Revenue ELSE NULL END AS Jun_Revenue,

CASE WHEN Month = 'Jul' THEN Revenue ELSE NULL END AS Jul_Revenue,

CASE WHEN Month = 'Aug' THEN Revenue ELSE NULL END AS Aug_Revenue,

CASE WHEN Month = 'Sep' THEN Revenue ELSE NULL END AS Sep_Revenue,

CASE WHEN Month = 'Oct' THEN Revenue ELSE NULL END AS Oct_Revenue,

CASE WHEN Month = 'Nov' THEN Revenue ELSE NULL END AS Nov_Revenue,

CASE WHEN Month = 'Dec' THEN Revenue ELSE NULL END AS Dec_Revenue

FROM Department

GROUP BY id;

 

*결과

list indices must be integers, not str

Jan_Revenue 만 놓고 봤을 때, id = 1  인 경우가 세 개 있으니 (null 2개 포함) SUM을 써야 하는군요. Feb_Revenue, Mar_Revenue도 마찬가지네요. 만약 id 별로 각 값이 하나씩 있다면 sum 함수를 사용하지 않아도 답이 동일해 지겠네요! 

Pivot 보다 Group by 들어가면서 코드 꼬이는게 이해가 안됐었는데 이제는 어느 정도 알 것 같네요. Group by를 하면서 맨 앞의 코드만 표시되니 이를 방지하기 위해 집계함수를 사용한다고 생각하면 될까요?

 

[ Group by - 전 ]

코드

SELECT id
       , CASE WHEN month='Jan' THEN revenue ELSE NULL END AS Jan_Revenue
       , CASE WHEN month='Feb' THEN revenue ELSE NULL END AS Feb_Revenue
       , CASE WHEN month='Mar' THEN revenue ELSE NULL END AS Mar_Revenue
FROM department

결과

| id | Jan_Revenue | Feb_Revenue | Mar_Revenue |
|----|-------------|-------------|-------------|
| 1  | 8000        | null        | null        |
| 2  | 9000        | null        | null        |
| 3  | null        | 10000       | null        |
| 1  | null        | 7000        | null        |
| 1  | null        | null        | 6000        |

 

 

[ Group by - 후 ]

코드

SELECT id
       , CASE WHEN month='Jan' THEN revenue ELSE NULL END AS Jan_Revenue
       , CASE WHEN month='Feb' THEN revenue ELSE NULL END AS Feb_Revenue
       , CASE WHEN month='Mar' THEN revenue ELSE NULL END AS Mar_Revenue
FROM department
GROUP BY id;

결과

id : 1 - Jan_Revenue 경우
(8000, null, null) 값이 그룹화 되는데 맨 앞에 있는 8000만 화면에 표시됩니다. 마찬가지로
id : 1 - Feb_Revenue 경우
( null, 7000, null) 값이 그룹화 되면서 맨 앞에 null 만 화면에 표시되는 거라고 볼 수 있겠네요.

| id | Jan_Revenue | Feb_Revenue | Mar_Revenue |
| -- | ----------- | ----------- | ----------- |
| 1  | 8000        | null        | null        |
| 2  | 9000        | null        | null        |
| 3  | null        | 10000       | null        |

이런 식으로 값이 나오기 때문에 집계함수를 통해 실제 존재하는 값을 조정해 주는 듯 하네요.

6

Idea님의 프로필 이미지
Idea
질문자

아...! 간단한 예시로 이해해주기 쉽게 설명해주셔서 정말 감사합니다! 덕분에 완벽하게 이해가 되었습니다 ^^

말씀하신대로 월에 받는 예산이 2번 이상인 경우에는 집계함수를 사용함에 있어서 주의를 해야겠네요

0

명확한 설명 너무 감사합니다. GROUP BY를 하면 집계함수를 꼭 써야만 하겠군요! 

0

안녕하세요 위의 내용에 덧붙여 질문드립니다.

 

왜 W3S에서는 categoryid == 1: ==을 써야하고, Leetcode는 =인지 궁금합니다

0

질문 챕터 : CASE를 활용한 테이블 피봇 리트코드 문제풀이(난이도 상)

안녕하세요, 혹시 아래와 같은 칼럼명들을 수동으로 일일이 이름 붙여주지 않고, 반복문을 활용하여 만들어내는 방법은 없을까요?

SELECT id,
        SUM(CASE WHEN month = 'Jan' THEN revenue ELSE NULL END) as JAN_Revenue,
        SUM(CASE WHEN month = 'Feb' THEN revenue ELSE NULL END) as Feb_Revenue,
        SUM(CASE WHEN month = 'Mar' THEN revenue ELSE NULL END) as Mar_Revenue,
        SUM(CASE WHEN month = 'Apr' THEN revenue ELSE NULL END) as Apr_Revenue,
        SUM(CASE WHEN month = 'May' THEN revenue ELSE NULL END) as May_Revenue,
        SUM(CASE WHEN month = 'Jun' THEN revenue ELSE NULL END) as Jun_Revenue,
        SUM(CASE WHEN month = 'Jul' THEN revenue ELSE NULL END) as Jul_Revenue,
        SUM(CASE WHEN month = 'Aug' THEN revenue ELSE NULL END) as Aug_Revenue,
        SUM(CASE WHEN month = 'Sep' THEN revenue ELSE NULL END) as Sep_Revenue,
        SUM(CASE WHEN month = 'Oct' THEN revenue ELSE NULL END) as Oct_Revenue,
        SUM(CASE WHEN month = 'Nov' THEN revenue ELSE NULL END) as Nov_Revenue,
        SUM(CASE WHEN month = 'Dec' THEN revenue ELSE NULL END) as Dec_Revenue
FROM department
GROUP BY id

 

저도 궁금해서 찾아봤는데, 바로 LeetCode 디스커션에서 찾을 수 있었어요. 

대신 MYSQL에서는 안 돌아가고, MY SQL SERVER에서 돌아갑니다.  

- 디스커션 원글: https://leetcode.com/problems/reformat-department-table/discuss/1958063/EASY-MS-SQL-SOLUTION-WITH-PIVOT-90-HIGHER

- MS SQL 공식 문서: https://docs.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot?view=sql-server-ver15

 

--------------

SELECT id

     , jan as Jan_Revenue 

     , feb as Feb_Revenue 

     , mar as Mar_Revenue 

     , apr as Apr_Revenue

     , may as May_Revenue 

     , jun as Jun_Revenue 

     , jul as Jul_Revenue 

     , aug as Aug_Revenue 

     , sep as Sep_Revenue

     , oct as Oct_Revenue 

     , nov as Nov_Revenue 

     , dec as Dec_Revenue

FROM department

 

PIVOT

(sum(revenue)

FOR month

    in ([jan],[feb],[mar], [apr], [may], [jun],[jul],[aug],[sep],[oct],[nov],[dec])

)AS pvt

Idea님의 프로필 이미지
Idea

작성한 질문수

질문하기