작성
·
876
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번은 데이터가 하나씩밖에 안 들어있어서 계산해볼것도 없겠네요. 연습삼아 가짜 데이터를 넣고 계산 해보시면 좋겠습니다.
이해하는데 도움이 되었으면 좋겠네요.
질문과, 답변을 강의에 링크로 걸고 다른 분들도 공부하시는데 도움이 되도록 할게요.
좋은 질문 해주셔서 감사합니다!
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
아...! 간단한 예시로 이해해주기 쉽게 설명해주셔서 정말 감사합니다! 덕분에 완벽하게 이해가 되었습니다 ^^
말씀하신대로 월에 받는 예산이 2번 이상인 경우에는 집계함수를 사용함에 있어서 주의를 해야겠네요
0
0
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에서 돌아갑니다.
- 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
혹시, sum을 쓰지 않고 그냥 group by 만 쓰면
왜 오류가 나는지 더 추가 설명을 받을 수 있을까요ㅠㅠ?