본문 바로가기

데이터베이스/SQL & PL/SQL

[SQL] 그룹으로 묶어서 관리해봅시다, GROUP BY!


이제 이쯤 보셨다면 SQL이랑은 많이 친해졌을듯 한데요~
조금만더 열심히 해요~ 저두 열심히 한답니다!!

앞에서 SUM(), AVG()에 대해서 조금 했었죠?
이와 같은 함수와 같이 쓰이는게 'GROUP BY'입니다.

조금 눈치 채셨을지는 모르겠어요.
이 구문은 데이터들을 묶어서 쿼리를 처리할때 쓰인답니다.

묶는다라.. 감이 안잡히시나요?
간단합니다.

이상한 예이지만.
초등학교 전국 체전이 있습니다.

여기서 우리는 A 부터 Z까지 26개 초등학교가 있는데요.
우리는 여기서 각 초등학교의 참가한 학생수를 알고 싶은겁니다.
각!! 학교별로 말이죠.

그러면 여기서 A라는 학교에 속해있는 100명의 학생들은(가정) A라는 학교라는 공통점이 있고,
B라는 학교에 속해있는 120명의 학생들은 B라는 같은 학교를 다닌다는 공통점이 있듯이,
모든 학교의 학생들은 자기가 속해있는 학교 즉, 그룹이 있습니다.
이렇게 모두 공통된 기준을 가지고 묶어주는 것을 SQL에서는 GROUP BY 라고 합니다. 

자 본격적으로 예를 볼까요?
SQL> SELECT department_id, SUM(salary)
         FROM hr.employees
         GROUP BY department_id;

이라고 썼습니다. 무슨 뜻일까요? 차례차례 해석해볼께요.
"hr스키마가 가지고 있는 employees 테이블로부터 부서 아이디를 기준으로 싸그리(?) 묶어서
부서별 월급의 합계를 알고 싶다." 입니다.

이때 GROUP BY 뒤에 써주는 컬럼명은 묶어주는 기준이 됩니다.
이해가시나요? 일단 결과를 보고 한가지 더해보죠.
이때 결과는 부서 아이디별, 즉 부서별 사원들의 월급 합계입니다.



조금 다르게 조건을 달고 갑니다.
"나는 부서별로 월급의 합계를 보고 싶은데, 그 합계 10000 이상인 그룹들만 보고 싶다."
라고 할때 어떻게 해야 할까요?

조건이니까 WHERE절을 써서 salary 의 합이라고 하니까 SUM() 함수를 적절히 쓰면 될까요?
아닙니다. GROUP BY에도 WHERE 절 처럼 조건을 달 수 있습니다.
그건 HAVING 절을 사용해서인데요.

다음과 같이 적을 수 있겠습니다.
SQL> SELECT department_id, SUM(salary)
         FROM hr.employees
         GROUP BY department_id
         HAVING SUM(salary)>10000;


자 보세요. 위쪽의 조회된 쿼리에서 부서별 salary가 10000 이상인 곳만 조회 되었죠?
이렇게 GROUP BY에 대한 조건을 걸때는 WHERE절이 아니라 HAVING를 쓰는 겁니다.

그렇다면 GROUP BY절과 WHERE 절은 같이 못쓰는 걸까요!?
그렇지 않습니다. 다만 쿼리의 처리되는 순서에 따라 해석이 달라지는 것 뿐입니다.
다음과 같이 쿼리가 있다면 해석되는 순서는 다음의 옆에 있는 숫자순번과 같습니다.
SELECT
FROM
WHERE          --1
GROUP BY     --2
HAVING         --3,
ORDER BY     --4

이렇게 처리 되겠는데요. 우선 WHERE 절부터 조건이 먼저 걸립니다.
WHERE절부터 조건에 걸려서 조회되는 데이터들 속에서 GROUP BY 에 명시되어 있는 컬럼을 기준으로 데이터들을 묶고
처리가 되면 HAVING 절에서 그 처리된 데이터들을 다시 조건 처리합니다.
+로 ORDER BY를 통해서 마지막으로 정렬을 하게 되는거죠.

이해가 안가신다구요?
그럼 예제를 보여드릴게요.

SQL> SELECT department_id, SUM(salary)
         FROM hr.employees
         WHERE hire_date>TO_DATE('00-01-01', 'YY-MM-DD')
         GROUP BY department_id
         HAVING SUM(salary)>4000
         ORDER BY department_id;

해석해 보세요!!
간단히 하자면 .. 간단하지 않군요 ^^;

우선 employees테이블로부터 (WHERE절) 2000년 이후의 입사직원들에 한해서 (GROUP BY) 부서별로 월급의 합계를 알아볼건데,
(HAVING) 그 합계라 4000 이상인 부서만 보겠다. 그리고 조회된 결과를 (ORDER BY) 부서  아이디 를 올림차순으로 해서 보겠다.

결과를 마지막으로 글을 마무리 짓겠습니다.