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

hyemin님의 프로필 이미지

작성한 질문수

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

case 문을 이해하기 위해 직접 sql editor에 코드를 작성해 보았는데 질문이 있습니다

작성

·

223

2

SELECT CASE 

WHEN employeeid > 0 AND employeeid<5 THEN '사원'

            WHEN employeeid > 5 AND employeeid<10 THEN '과장'

            ELSE '사장'

       END AS new, *

       

FROM orders

GROUP BY new

        

-- 이렇게 코드를 짰고요

결과물은 이렇습니다

Number of Records: 3
new OrderID CustomerID EmployeeID OrderDate ShipperID
과장 10249 81 6 1996-07-05 1
사원 10250 34 4 1996-07-08 2
사장 10248 90 5 1996-07-04 3

여기서 궁금한 점은, 코드를 보시면 아시겠지만 저는 SELECT 안에 new로 정의된 CASE문과 *를 넣었는데요,

그렇다면 new 라는 GROUP 옆에 있는 값들은,, 무슨 값인가요?

평균값이나 COUNT 값도 아닌 것 같고, 카테고리 안에는 분명 다양한 값이 있어야 할 텐데 (왜냐면 원래의 값에 0~5의 값이 한 개가 아니었고(사원의 경우) 그건 다른 case들도 마찬가지) 왜 하나만 나오는 걸까요?? 

저 값은 무슨 값인가요?? 그냥 임의로 하나의 값, 혹은 가장 위에 있는 값만 뽑는 건가요? ㅠㅠ

답변 4

0

이보민님의 프로필 이미지
이보민
지식공유자

안녕하세요 혜민님,

설명이 명확하지 못했나보아요 ㅠ

'*' 기호가 GROUP BY로 그룹핑 하기 이전에 통용되는 기호라고 말씀하셨는데 해당 부분이 잘 이해가 되지 않네요. 제가 위에 첨부드렸던 내용은 기호나 명령의 순서의 문제이기 이전에 SQL 내부에서 구현되어있는 처리 방법상의 문제라고 생각해주시면 좋을 것 같아요.

SQL도 사람이 만든 프로그램이다보니 코드 구현상의 논리적인 오류도 있을 수 있거든요. 그런 종류의 문제라고 생각하시면 이해가 좀 더 쉬우실지 모르겠네요.

그리고 '그룹핑한 뒤의 모든 column'을 본다는 것은 기본적으로 불가능합니다. GROUP BY 함수 자체가 그룹핑을 해서 묶은 각각의 데이터를 이용해 연산을 하거나 가공을 하기 위해 만들어진 함수이기 때문이에요. 아마 말씀하신 것처럼 어떤 값을 기준으로 데이터를 구분해서 보고 싶긴 한데 전체 column의 내용들은 다 보고 싶은 경우라면 GROUP BY가 아니라 그냥 ORDER BY를 이용하면 되겠죠?

혹시 제가 질문의 요지를 잘못 파악했거나 또 궁금한 것이 있으시면 알려주세요 :)

감사합니다.

0

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

세세하게 신경 써 주셔서 감사합니다 ㅎㅎ 

추가 질문이 있는데요, 제가 쓴 코드의 경우 '*' 기호가 GROUP BY로 그룹핑하기 이전에 통용되는 기호이기 때문에 생긴 오류라는 뜻인가요? '그룹핑한 뒤의 모든 column'을 의미할 수는 없는 건가요? 저도 질문하면서 이렇게 여쭈는 것이 맞나 싶지만 ㅠㅠ 감사합니닷

0

이보민님의 프로필 이미지
이보민
지식공유자

그리고 혹시 CASE문에서 의도하신 것이 employeeid가 5인 유저를 '사장'으로 하고 싶으셨던 것이 아니셨다면,

보내주신 CASE문에서는 '사원'과 '과장'을 나누는 조건 사이에 employeeId = 5인 경우가 누락되어있는 것 같습니다. 만약 employeeid가 1~5인 유저들을 '사원'으로 분류하고, 6~9인 유저들을 '과장'으로 분류하고 10 이상인 유저를 '사장'으로 분류하고 싶으셨던 것이라면 CASE문을 아래와 같이 수정하시는 것이 더 정확한 결과를 얻으실 수 있으실 거에요.

WHEN employeeid > 0 AND employeeid <= 5 THEN '사원'

WHEN employeeid > 5 AND employeeid<10 THEN '과장'

다음에 CASE문에서 구간을 나누실 때에는 구간 사잇값을 어디에 포함시킬 것인지 조금 더 신경써서 조건을 만들어주시면 완벽한 CASE문이 될 것 같아요!

감사합니다.

0

이보민님의 프로필 이미지
이보민
지식공유자

안녕하세요 혜민님,

해당 부분은 MYSQL 인터프리터 버전 때문에 생기는 오류로 보이는데요.

MYSQL 버전 5.6 이하에서는 GROUP BY를 하고 그룹핑에 사용되지 않은 컬럼을 SELECT 했을 경우에 서버에서 임의로 선택한 값을 표시하는 방식으로 내부 로직이 구현되어 있었습니다. 그러나 이렇게 되면 혜민님께서 이렇게 문의 주신 것처럼 이 데이터들이 어떻게 해서 선별 된 것인지 쿼리를 작성한 사람조차 알 수 없는 경우가 됩니다.

때문에 5.7 이상의 MYSQL에서는 위와 같이 그룹핑 할 것으로 명시하지 않은 컬럼을 SELECT문 내에서 요청할 경우 에러 메세지를 띄워 그룹핑에 사용하지 않은 컬럼은 SELECT에 사용하지 못하도록 해당 기능을 보완해 두었습니다.

아마도 우리가 사용하는 w3school의 인터프리터 버전이 5.6 이하라서 해당 부분의 기능이 보완되지 않은 것 같습니다.

만약 혜민님께서 버전 5.6 이하의 MYSQL 인터프리터를 사용하시는 곳에서 작업을 하게 되셔서 위와같이 GROUP BY에 명시하지 않은 컬럼으로 데이터 추출이 가능하다고 하더라도, GROUP BY를 해줄 때에는 반드시 명시된 컬럼과 집계함수를 이용한 데이터 추출 방식을 사용하실 것을 권장드릴게요.

해당부분과 관련한 MYSQL 문서를 참고자료로 남겨드리니 궁금하시면 읽어보세요.

MySQL 5.7.5 and up implements detection of functional dependence. If the ONLY_FULL_GROUP_BY SQL mode is enabled (which it is by default), MySQL rejects queries for which the select list, HAVING condition, or ORDER BY list refer to nonaggregated columns that are neither named in the GROUP BY clause nor are functionally dependent on them. (Before 5.7.5, MySQL does not detect functional dependency and ONLY_FULL_GROUP_BY is not enabled by default. For a description of pre-5.7.5 behavior, see the MySQL 5.6 Reference Manual.)

https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

MySQL extends the standard SQL use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause. This means that the preceding query is legal in MySQL. You can use this feature to get better performance by avoiding unnecessary column sorting and grouping. However, this is useful primarily when all values in each nonaggregated column not named in the GROUP BY are the same for each group. The server is free to choose any value from each group, so unless they are the same, the values chosen are nondeterministic. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause. Result set sorting occurs after values have been chosen, and ORDER BY does not affect which values within each group the server chooses.

[출처] https://dev.mysql.com/doc/refman/5.6/en/group-by-handling.html

hyemin님의 프로필 이미지

작성한 질문수

질문하기