본문 바로가기

Data Literacy/SQL

Chapter 2. JOIN을 이용한 데이터 조합 - (8) 그룹화 : GROUP BY & HAVING 4

PostgreSQL logo image

 

 

지금까지 GROUP BY를 배워오면서 짚고 넘어가지 않은 중요한 원칙이 하나 있습니다. 바로 [GROUP BY에서 선언한 열 이외의 열은, SELECT 프레이즈에서 집계함수를 사용하지 않은 채 작성해서는 안된다]입니다. 지금까지 예제를 작성할 때, 별다른 언급이 없었을 뿐이지 잘 생각해 보면 이러한 방식으로 예제를 작성해 왔었던 것 같습니다!

 

그럼 '왜' GROUP BY에서 선언되지 않은 열은 반드시 집계함수와 함께 SELECT에서 선언해야 하는 것일까요? 한번 그 이유를 살펴보도록 하겠습니다. 우선 지금까지 사용한 SAMPLE00 테이블을 이용해서 살펴보겠습니다. 기억이 잘 나지 않을 수 있으니, 해당 테이블을 다시 조회해 보겠습니다. 

 

select *
  from sample00 s

 

 

 

이제 기본적인 GROUP BY 동작 원리에 대해서 다시 한번 짚고 넘어가겠습니다. 예를 들어, GROUP BY에서 NAME을 기준으로 출력하도록 합니다. 여기서 중요한 것은 NAME이라는 열의 데이터 값을 기준으로 그룹을 만든다는 점 입니다. 그리고, 그 그룹당 하나의 행을 갖게 됩니다. 이것이 기본 원칙입니다. A가 100개가 있어도, A라는 그룹 열은 1개인 것입니다. 

 

select name
  from sample00 s
 group by name;

 

 

 

그런데 만약에, 여기에 집계함수가 아닌 QUANTITY 열을 출력하도록 정의해 보겠습니다. 그럼 어떠한 오류가 발생하게 될까요? 

 

select name, quantity 
  from sample00 s
 group by name;
 
 -- SQL Error [42803]: 오류: column "s.quantity" 는 
 -- 반드시 GROUP BY 절내에 있어야 하든지 또는 집계 함수 내에서 사용되어져야 한다

 

위와 같이 QUANTITY 열은 집계함수를 사용하거나 GROUP BY에서 선언된 열이어야 합니다. 자, 그럼 왜 오류가 생기는지 짚어볼까요? 우선 GROUP BY에서 NAME을 기준으로 그룹을 만들도록 선언했고 SELECT에선 NAME을 지정했습니다. 그래서 위와 같이 A, B, C, [NULL]이라는 그룹이 만들어졌습니다.

 

그리고 QUANTITY를 출력하려고 하는데, QUANTITY는 원래 테이블에서 A가 1인 열과 A가 2인 열이 존재했습니다. 그럼, 별도의 집계함수 사용이 없었기 때문에 클라이언트에서는 A라는 그룹에 어떤 QUANTITY를 표시해야 할지 결정할 수가 없는 것입니다. 

 

그런데 만약, 이 QUANTITY열을 집계함수 SUM을 이용해서 표시하게 되면 이 값은 그룹별로 '하나의 값'이 되어 리턴이 가능해 집니다. (이것은 NO 열의 경우에도 동일하게 적용되는 원리입니다)

 

자, 그럼 아래와 같이 쿼리를 작성해 보겠습니다. 

 

select min(no), name, sum(quantity) 
  from sample00 s
 group by name;

 

NAME을 기준으로 그룹을 만들었기 때문에 SELECT에서 NAME은 그대로 사용했습니다. 단, QUANTITY의 경우 각 그룹 별로 수량을 모두 합산한 값을 산출하도록 SUM( )을 사용하였습니다. NO열의 경우에는 임의로 '가장 작은 NO 값'을 표시하도록 MIN( ) 집계 함수를 사용하였습니다. 즉, NO와 QUANTITY 모두 '하나의 값'이 리턴되도록 집계함수를 사용한 것입니다.

 

 

참고로 GROUP BY에서 NAME과 QUANTITY를 모두 선언했다면, SELECT에서 두 개의 열을 그대로 사용하면 됩니다. 

 

select name, quantity  
  from sample00 s
 group by name, quantity ;

 

 

 

 


 

 

여기서 한가지, 실습을 제대로 따라오신 분들이라면 눈치채셨겠지만 GROUP BY를 사용해 데이터를 출력했을 때 데이터 정렬이 꽤나 뒤죽박죽으로 나오는 경우가 많습니다. 이럴 때는 ORDER BY를 사용해 주면 됩니다. 우리가 앞선 아티클에서 살펴볼 때 잠깐 언급이 되었는데, ORDER BY는 쿼리 프레이즈 중에서 가장 마지막으로 적용됩니다. 

 

select name, count(name), sum(quantity)
  from sample00 s 
 group by name
 order by sum(quantity) desc;