Oracle SQL 강좌
GROUP BY와 HAVING절 16 16 99,999+

by 구루비 GROUP BY HAVING DISTINCT [2002.01.20]


GROUP BY절

  • - GROUP BY 절은 데이터들을 원하는 그룹으로 나눌 수 있다.
  • - 나누고자 하는 그룹의 컬럼명을 SELECT절과 GROUP BY절 뒤에 추가하면 된다.
  • - 집계함수와 함께 사용되는 상수는 GROUP BY 절에 추가하지 않아도 된다. (개발자 분들이 많이 실수 함)
  • - 아래는 집계 함수와 상수가 함께 SELECT 절에 사용되는 예이다.
-- 부서별 사원수 조회
SELECT '2005년' year, deptno 부서번호, COUNT(*) 사원수
  FROM emp
 GROUP BY deptno
 ORDER BY COUNT(*) DESC;


YEAR     부서번호     사원수
------ ---------- ----------
2005년         30          6
2005년         20          5
2005년         10          3

아래 예제는 부서별로 그룹하여 부서번호, 인원수, 급여의 평균, 급여의 합을 조회하는 예제이다.

 
SELECT deptno, COUNT(*), ROUND(AVG(sal)) "급여평균", 
       ROUND(SUM(sal)) "급여합계"
  FROM emp
 GROUP BY deptno;


  DEPTNO   COUNT(*)    급여평균    급여합계
-------- ---------- ---------- ----------
      30          6       1567       9400
      20          5       2175      10875
      10          3       2917       8750

아래 예제는 업무별로 그룹하여 업무, 인원수, 평균 급여액, 최고 급여액, 최저 급여액 및 합계를 조회하는 예제이다.

 
SELECT job, COUNT(empno) "인원수", AVG(sal) "평균급여액",
       MAX(sal) "최고급여액", MIN(sal) "최저급여액", 
       SUM(sal) "급여합계"
  FROM emp
 GROUP BY job;


JOB           인원수   평균급여액   최고급여액   최저급여액    급여합계
----------- -------- ---------- ---------- ---------- ----------
CLERK              4     1037.5       1300        800       4150
SALESMAN           4       1400       1600       1250       5600
PRESIDENT          1       5000       5000       5000       5000
MANAGER            3 2758.33333       2975       2450       8275
ANALYST            2       3000       3000       3000       6000 

  • - GROUP BY 절은 집계 함수 없이도 사용 될 수 있다.(DISTINCT와 용도가 비슷해 짐)
  • - 아래 예제를 보면 GROUP BY는 말 그대로 그룹을 나누는 역할을 한다.
-- GROUP BY를 이용한 부서번호 조회 예
SELECT deptno
  FROM emp
 GROUP BY deptno;


DEPTNO
------
    30
    20
    10

DISTINCT와 GROUP BY절

  • - DISTINCT와 GROUP BY 개념에 대해서 좀 더 이해를 해보자.
  • - DISTINCT는 주로 UNIQUE(중복을 제거)한 컬럼이나 레코드를 조회하는 경우 사용한다.
  • - GROUP BY는 데이터를 그룹핑해서 그 결과를 가져오는 경우 사용한다.
  • - 하지만 두 작업은 조금만 생각해보면 동일한 형태의 작업이라는 것을 쉽게 알 수 있으며, 일부 작업의 경우 DISTINCT로 동시에 GROUP BY로도 처리될 수 있는 쿼리들이 있다.
  • - 두 기능 모두 Oracle9i까지는 sort를 이용하여 데이터를 만들었지만, Oracle10g 부터는 모두 Hash를 이용하여 처리한다.
  • - 그래서 DISTINCT를 사용해야 할지, GROUP BY를 사용해서 데이터를 조회하는 것이 좋을지 고민되는 경우들이 가끔 있다.

아래의 예제는 동일한 결과를 반환한다.

-- DISTINCT를 사용한 중복 데이터 제거
SELECT DISTINCT deptno FROM emp;


-- GROUP BY를 사용한 중복 데이터 제거
SELECT deptno FROM emp GROUP BY deptno;


DEPTNO
------
    30
    20
    10

하지만 곰곰히 생각해 보면 GROUP BY와 DISTINCT는 각자 고유의 기능이 있다

집계함수를 사용하여 특정 그룹으로 구분 할 때는GROUP BY 절을 사용하며, 특정 그룹 구분없이 중복된 데이터를 제거할 경우에는 DISTINCT 절을 사용 하도록 하자

-- 아래와 같은 기능은 DISTINCT를 사용하는 것이 훨씬 효율적이다.
SELECT COUNT(DISTINCT d.deptno) "중복제거 수", 
       COUNT(d.deptno) "전체 수"
  FROM emp e, dept d
 WHERE e.deptno = d.deptno;


-- 집계 함수가 필요한 경우는 GROUP BY를 사용해야 한다.
SELECT deptno, MIN(sal)
  FROM emp 
 GROUP BY deptno;

HAVING 절

  • - WHERE 절에서는 집계함수를 사용 할 수 없다.
  • - HAVING 절은 집계함수를 가지고 조건비교를 할 때 사용한다.
  • - HAVING절은 GROUP BY절과 함께 사용이 된다.

아래 예제는 사원수가 다섯 명이 넘는 부서와 사원수를 조회하는 예제이다.

SELECT b.dname, COUNT(a.empno) "사원수" 
  FROM emp a, dept b
 WHERE a.deptno = b.deptno
 GROUP BY dname
HAVING COUNT(a.empno) > 5;


DNAME          사원수
------------ -------
SALES              6

아래 예제는 전체 월급이 5000을 초과하는 JOB에 대해서 JOB과 월급여 합계를 조회하는 예이다. 단 판매원(SALES)은 제외하고 월 급여 합계로 내림차순 정렬하였다.

SELECT job, SUM(sal) "급여합계"
  FROM emp  
 WHERE job != 'SALES'      -- 판매원은 제외
 GROUP BY job              -- 업무별로 Group By 
HAVING SUM(sal) > 5000     -- 전체 월급이 5000을 초과하는
 ORDER BY SUM(sal) DESC;   -- 월급여 합계로 내림차순 정렬


JOB                  급여합계
------------------ ----------
MANAGER                  8275
ANALYST                  6000
SALESMAN                 5600

참고링크

- 강좌 URL : http://www.gurubee.net/lecture/1032

- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^

- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.

by goguy [2004.05.08 20:55:23]
SELECT b.dname, COUNT(a.empno)
FROM emp a, dept b
WHERE a.deptno = b.deptno
GROUP BY dname
HAVING COUNT(a.empno) > 5
분석하죠
1.SELECT
2.FROM
3.WHERE
4.GROUP GY
5.HAVING

2. 두개의 테이블이 메모리에 적재되고여
3. 조건에 의해 하나의 테이블로 조합되고
4. 에 의해 그룹으로 구분되지고여
6. 에 그룹함수 조건에 의해 테미블이 재조합 되겠지여
1. 에 의해 다시 그룹함수계산으로 '사원수가 5명이 넘는 부서의 부서명과 사원수를 출력' 테이블이 제조합 되면서 뿌려지겠지여..




by goguy [2004.05.08 21:22:46]
초보자님 질문에 대한 도움입니다.
스미스와 같은 매니저를 가진 직원들은 열거하시요
문제의 핵심은 테이블이 두개로 데이타가 존재하느냐 아니면 하나로만 존재하느냐 입니다
두개의 테이블에 나누어서 존재한다면 JOIN을 이용하면 되고요
하나의 테이블에 존재한다면 SUB QUERY를 이용해야 됩니다.
문제를 풀기 위해서는 두가지를 공부하셔야겠지요...

by 배재민 [2004.12.08 10:16:24]
- HAVING절은 GRUOP 함수를 가지고 조건비교를 할 때 사용 합니다.
- WHERE → GRUOP BY → HAVING → ORDER BY순으로 쿼리문이 와야 됩니다.

에서 GROUP 철자가 틀렸어요;; 사소한거 지적 해서 죄송합니다;; 공부하다가 보니깐 그런게 보이네요;;

by 정용태 [2005.05.10 16:01:58]
WHERE job NOT IN ('SALES') -->> WHERE job NOT IN ('SALESMAN') 이죠!!

처음 공부하시는 분들은 헥갈려 하실까바.. 사소한거지만요^^

by 초보자 [2005.10.04 15:13:47]
HAVING절 예제2에서, 조건에는 SALESMAN을 제외하라고 했는데, 결과에는 왜
SALESMAN이 출력된 건가요?
NOT IN('SALES')에서 SALESMAN 이 SALES라고 명시되서 결과에 반영된 건가요?

by smile [2005.11.09 20:20:35]
퍼갑니다. ^^

by kaiger [2006.12.11 17:51:23]
어렵당 ㅠㅠ

by 똘마니 [2007.02.07 11:28:05]
SALESMAN(판매원)을 빼야하는데 SALES(판매부서)로 잘못 뺀거 같네요~^^
용태님 처럼 고치면 SALESMAN(판매원) 제외한 결과값이 나옵니다~^^

by 다정 [2007.05.03 21:01:39]
음., 다들 싸우면서 크는거래요

by 뽀 [2007.11.02 18:29:48]
쥐미 =ㅂ=

by 물어 콱~! [2007.11.13 10:12:57]
좌절이신가.ㅡㅡ;;;

by 양한마리 [2010.02.03 10:36:40]
이해가 쏙쏙 들어오네요~ ^ ^

by 송죽 [2011.08.12 17:00:58]
도움이 되는데 아직도 명령어처리 순서가 어렵네요.

by 여비몬 [2013.01.28 19:10:28]
 전 지금 이게 제일 멘붕이네요..

by 제로엔나 [2015.02.27 05:09:15]

GROUP BY deptno로 SELECT문에서 부서별 데이터를 보여줄 수 있게 한다 그런거죠??

오오 점점 이해가 가고 있어. 좋아~


by 9ruby [2022.07.19 14:03:37]

안녕하세요. 블로그에 해당글 링크 남기겠습니다^^

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입