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

Idea님의 프로필 이미지

작성한 질문수

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

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

20.04.15 15:10 작성

·

844

11

안녕하세요.

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

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

2020. 04. 15. 15:44

안녕하세요 :)

일단 아래 참고자료를 자세하게 읽어봐주시면 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번은 데이터가 하나씩밖에 안 들어있어서 계산해볼것도 없겠네요. 연습삼아 가짜 데이터를 넣고 계산 해보시면 좋겠습니다.

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

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

learn&learn님의 프로필 이미지

2021. 06. 06. 18:26

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

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

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

2021. 06. 07. 21:27

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

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

감사합니다!

[SQL 실전반 4기] 나니님의 프로필 이미지

2022. 03. 29. 15:34

위에 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

[SQL 실전반 4기] 틸다님의 프로필 이미지

2022. 04. 20. 11:33

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

초보개발자님의 프로필 이미지

2023. 04. 05. 12:22

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
질문자

2020. 04. 15. 15:54

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

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

0

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

0

강재연님의 프로필 이미지

2021. 12. 15. 21:02

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

 

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

0

유동현님의 프로필 이미지

2021. 10. 23. 21:14

질문 챕터 : 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

 

[SQL 실전반 4기] 틸다님의 프로필 이미지

2022. 04. 20. 11:49

저도 궁금해서 찾아봤는데, 바로 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님의 프로필 이미지

작성한 질문수

질문하기