티스토리 뷰

SQL

그룹핑을 알아보자 (feat.GROUP BY, HAVING)

인공지능끙정 2023. 1. 29. 11:49
반응형

안녕하세요, 끙정입니다.

 

오늘은 다른 형식의 집계 함수인 GROUP BY에 대해 알아보겠습니다.

 

1.GROUP BY

우리가 만일 각 부서별 평균 월급을 알고 싶다면, 부서마다 AVG 함수를 호출하면 됩니다.

다음과 같이 말이죠.

 

 

그러나 굉장히 비효율적이라는 것을 아실겁니다.

부서가 수십개라면, 수십개의 쿼리를 따로 날려줘야하고,

한 눈에 보기도 힘듭니다.

이럴때 사용하는 것이 바로 GROUP BY입니다.

 

GROUP BY는 기준 필드가 같은 레코드를 모아 통계값을 구합니다.

또한 기준 필드는 집계 함수와 함께 쓸 수 있어 목록도 보기 좋게 출력할 수 있습니다.

 

/* GROUP BY 와 필드를 넣어준다. */
SELECT depart, AVG(salary) FROM tStaff GROUP BY depart;

 

 

GROUP BY는 단지 그룹핑을 해주는 것 뿐이며, 어떤 통계를 낼 것인가는 필드 목록의 집계 함수에 따라 달라집니다.

여러 개의 집계 함수를 동시에 사용할 수도 있습니다.

 

/* depart 별로 GROUP BY를 한다. */
/* depart 이름을 출력해주고 */
/* 부서별 레코드의 COUNT를 출력해주고 */
/* 부서별 joindate의 최댓값을 출력해주고 */
/* 부서별 score의 평균값을 출력한다. */
SELECT depart, COUNT(*), MAX(joindate), AVG(score) FROM tStaff GROUP BY depart;

 

 

1-1. GROUP BY의 기준 필드

GROUP BY의 목적은 그룹핑을 통한 그룹 통계를 내는 것이기 때문에 기준 필드를 어떤 것으로 할 것인지가 중요합니다.

고유값만이 존재하는 필드는 그룹핑이 되지 않기 때문에 의미가 없다는 것이지요.

 

이름별 Salary의 합?! 그룹핑의 의미가 없다.

기준 필드를 여러개 쓰는 것도 가능합니다.

기준 필드를 두 개를 쓴다면, 첫 번째 기준으로 나누고, 다시 두 번째 기준으로 또 나눕니다.

 

/* depart X gender 를 기준으로 그룹핑 한다. */
SELECT depart, gender, COUNT(*) FROM tStaff GROUP BY depart, gender;

 

각 부서별, 성별 기준으로 count

 

부서를 먼저 나누고 성별을 구분하는 것이나, 성별을 나눈 후 부서를 구분하는 것이나 결과는 같습니다.

출력 순서가 다른 것 뿐인데,

어차피 필드 순서는 필드 목록에서 지정이 가능하고,

레코드 순서는 ORDER BY로 조정이 가능하기 때문입니다.

 

 

2. HAVING

HAVING절은 GROUP BY의 다음에 오며, 통계 결과 중 출력할 그룹의 조건을 지정합니다.

WHERE절과 헷갈릴 수 있지만, 오직 GROUP BY의 조건절로만 쓰입니다.

 

/* 평균 임금이 340 이상인 부서만 출력하고 싶다. */
SELECT depart, AVG(salary) FROM tStaff GROUP BY depart HAVING AVG(salary) >= 340;

 

HAVING은 무조건 GROUP BY의 뒤에 오며, 정렬을 해주는 ORDER BY 보다 뒤로 갈 수는 없습니다.

언제나 출력을 마친 후에 정렬이 일어나기 때문입니다.

 

WHERE와 HAVING의 차이를 명확히 하기 위해 비교를 해보겠습니다.

 

/* HAVING 으로 조건을 준 쿼리 */
SELECT depart, AVG(salary) FROM tStaff GROUP BY depart HAVING AVG(salary) >= 340;

/* WHERE 로 조건을 준 쿼리 */
SELECT depart, AVG(salary) FROM tStaff WHERE salary >= 340 GROUP BY depart;

 

 

WHERE는 레코드에 조건을 거는 것이고,

HAVING은 그룹핑 된 결과에 조건을 거는 것입니다.

그렇기에 평균이 아예 다르게 집계 됩니다.

 

따라서 SELECT 문은 다음과 같은 순서를 가집니다.

 

SELECT 필드명 /* 이 필드를 출력해줘 */
FROM 테이블명 /* 이 테이블에 있는 */
WHERE 조건 /* 이 조건에 부합하는 레코드만 추려서 */
GROUP BY 필드기준 /* 그걸 이 필드기준으로 그룹핑 해줘 */
HAVING 조건 /* 그중에서 이 조건에 부합하는 그룹만 출력해줘 */
ORDER BY 필드기준 /* 마지막으로 그 결과를 이 필드를 기준으로 정렬 해줘 */

 

때때로 HAVING과 WHERE가 같은 결과를 출력해낼 때도 있지만,

내부적인 연산과정은 확연히 다릅니다.

쿼리는 효율성이 가장 중요하기 때문에 대체로 WHERE를 통해서 같은 결과를 출력하는 것이 빠를 것입니다.

다음과 같이 말이죠!

 

/* WHERE로 동일한 출력을 내보자 */
SELECT depart, MAX(salary) FROM tStaff
WHERE depart IN ('인사과', '영업부')
GROUP BY depart;

/* HAVING 으로 동일한 출력을 내보자 */
SELECT depart, MAX(salary) FROM tStaff
GROUP BY depart
HAVING depart IN ('인사과', '영업부');

 

 

두 쿼리는 동일한 결과를 냅니다-!

인사과, 영업부 중에서 그룹별로 가장 높은 임금을 출력해 달라는 쿼리입니다.

그러나 WHERE절을 쓴 쿼리는 모든 레코드에서 일단 인사과와 영업부 레코드만 추려서 그룹핑을 합니다.

반대로 HAVING절은 모든 레코드를 그룹핑해서 그 안에서 인사과와 영업부만 출력합니다.

출력 속도에 차이가 있는 것이 보이실 겁니다. (전자는 0.000 sec, 후자는 0.001 sec)

레코드가 몇개 없으면 별 차이 없지만,

레코드가 많다면 연산량이 급격히 늘어날 것입니다.

 

 

오늘은 그만 알아보겠습니다.

 

 

출처

http://www.yes24.com/Product/Goods/101637633

 

김상형의 SQL 정복 : 소문난 명강의 (무료특별판) - YES24

DBMS에 제약 없이 SQL을 활용한다!핵심 원리를 알려주는 SQL 바이블 DBMS 제품이나 개발툴이 아닌 SQL 언어 그 자체를 배우는 바이블 도서다. 특정 DBMS에 종속적인 사용법보다는 표준화된 데이터 관리

www.yes24.com

 

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함