▶ 그룹 함수

 

* 그룹 함수를 사용하는 경우 고려 사항
- NULL값은 무시된다.
- 반드시 단 하나의 값만을 반환한다.
- GROUP BY 설정 없이 일반 컬럼과 기술될 수 없다.

 

예제 1. 사원의 급여 평균을 검색한다.

SELECT AVG(sal) 평균급여, ROUND(AVG(sal)) 평균급여
FROM emp;

  평균급여   평균급여
---------- ----------
3167.57143       3168

 

예제 2. 사원들에게 지급된 보너스 총합과 보너스 평균을 검색한다.

SELECT SUM(comm) 총액,
ROUND(AVG(comm)) 평균, COUNT(comm) 수령인원,
ROUND(AVG(NVL(comm,0))) 환산평균, COUNT(*) 전체인원
FROM emp;

      총액       평균   수령인원   환산평균   전체인원
---------- ---------- ---------- ---------- ----------
     14780        869         17        704         21
     
     
SELECT COUNT(*) FROM emp
WHERE comm IS NOT NULL;

  COUNT(*)
----------
        17

null 값은 무시가 되기 때문에 위 방식은 문제가 발생한다. 

 

예제 3. 10번 부서원들보다 급여가 높은 사원을 검색한다.

SELECT eno 사번, ename 이름, dno 부서번호
FROM emp
WHERE sal > (SELECT MAX(sal) // 추천!!!
FROM emp
WHERE dno = '10');

SELECT eno 사번, ename 이름, dno 부서번호
FROM emp
WHERE sal > ALL(SELECT sal
FROM emp
WHERE dno = '10');

사번    이름       부서번호
------- ---------- ---------
0001    안영희     01

보통은 위의 두 방식 중 첫번째 방식처럼 사용한다. 단일행 서브쿼리로 사용한다.

 

▶ 그룹 함수와 GROUP BY절

SELECT [DISTINCT/ALL] 컬럼 or 그룹함수, ...
FROM 테이블
WHERE 조건
GROUP BY Group대상
ORDER BY 정렬대상 [ASC/DESC]

- 통계정보를 출력할 경우 같은 정보를 가진 사람끼리 통계정보를 출력하기 위해 GROUP BY 절을 사용한다.

- GROUP BY 절에 있는 컬럼 명을 SELECT절 일반컬럼에 꼭 넣어준다.

- 카디널리티: 값의 종류 (ex. 성별은 카디널리티 낮음, 이름은 카디널리티 높음)

 

예제 4. 업무별 평균 급여, 평균 연봉과 부서별 평균 연봉을 검색한다.

SELECT job 업무, ROUND(AVG(sal)) 평균_급여,
ROUND(AVG(sal*12+NVL(comm,0))) 평균_연봉
FROM emp
GROUP BY job;

업무     평균_급여  평균_연봉
------- ---------- ----------
분석          2900      35500
지원          3803      47467
개발          2782      34282
모델링        4300      51883
경영          4800      57600
회계          2380      28790

 

SELECT d.dno 부서번호, dname 부서명,
ROUND(AVG(sal*12+NVL(comm,0))) 평균_연봉
FROM dept d, emp e
WHERE d.dno = e.dno
GROUP BY d.dno, dname
ORDER BY d.dno;

부서번호  부서명   평균_연봉
--------- ------- ----------
01        총무         49833
02        회계         27990
10        ERP          42664
20        ISP          38768
30        ITEA         43323
40        CRM          25200

dno만 그룹바이 해도 되지만 dname를 한 이유는 select절의 일반컬럼에 dno, dname 둘다 있기 때문에 dname도 그룹바이절에 적어준다.

 

예제 5. 부서별로 급여 평균의 최대 값과 최소 값을 검색한다.

SELECT dno 부서번호,
MAX(AVG(sal)) 최대평균, MIN(AVG(sal)) 최소평균
FROM emp
GROUP BY dno;
SELECT dno 부서번호,
       *
1행에 오류:
ORA-00937: 단일 그룹의 그룹 함수가 아닙니다

SELECT MAX(AVG(sal)), MIN(AVG(sal))
FROM emp
GROUP BY dno;

MAX(AVG(SAL)) MIN(AVG(SAL))
------------- -------------
         4070          2100

dno로 그룹바이해도 select 절에 컬럼이 하나씩밖에 안나오는 그룹함수를 적었기 때문에 select 절에 dno를 뺀다.

 

예제 6. 그룹 대상 컬럼과 그룹 함수를 이용한 검색 결과 확인

SELECT dno 부서번호, COUNT(*) 인원수
FROM emp
WHERE job != '개발'
GROUP BY dno, job;

부서번호      인원수
--------- ----------
10                 1
02                 1
20                 1
20                 1
01                 1
01                 2
02                 4

부서번호      인원수
--------- ----------
10                 1
30                 1
10                 2
20                 1

 

예제 7. 각 부서별 최소 급여를 받는 사원의 정보를 검색한다.

SELECT d.dno, dname, eno, ename, sal
FROM emp e, dept d
WHERE d.dno=e.dno
AND (d.dno, sal) IN (SELECT dno, MIN(sal)
FROM emp
GROUP BY dno)
ORDER BY d.dno;

DNO     DNAME   ENO     ENAME             SAL
------- ------- ------- ---------- ----------
01      총무    0202    손하늘           3510
02      회계    0309    김선유            900
10      ERP     0269    권나현           2600
20      ISP     2002    제갈민           1520
30      ITEA    2007    이초록           1989
40      CRM     2008    윤고은           2100

 

실습
1. 각 학과별 학생 수를 검색한다.

SELECT major 학과, COUNT(sno)
FROM student
GROUP BY major;

학과    COUNT(SNO)
------- ----------
화학            17
유공            18
생물            17
식영            19
물리            16


2. 화학과와 생물학과 학생 4.5 환산 평점의 평균을 각각 검색한다.

SELECT major 학과, TO_CHAR(AVG(avr*4.5/4), '90.99') "4.5 환산평균"
FROM student
WHERE major IN ('화학', '생물')
GROUP BY major;

학과    4.5 환산평균
------- ------------
화학      2.45
생물      2.76


3. 부임일이 10년 이상 된 직급별(정교수, 조교수, 부교수) 교수의 수를 검색한다. ♠♠♠

SELECT orders 직위, COUNT(orders) "부임일이 10년 이상 교수 수"
FROM professor
WHERE (TO_CHAR(sysdate, 'YYYY')-TO_CHAR(hiredate, 'YYYY')+1)>=10
GROUP BY orders;

직위    부임일이 10년 이상 교수 수
------- --------------------------
조교수                           7
정교수                           8
부교수                           9


4. 과목명에 화학이 포함된 과목의 학점수 총합을 검색한다.

SELECT cname 과목이름, SUM(st_num) 학점수총합
FROM course
WHERE cname LIKE '%화학%'
GROUP BY cname;

과목이름     학점수총합
------------ ----------
무기화학              2
환경화학              2
일반화학실험          2
일반화학              3
핵화학                3
식품화학              3
유기화학              3


5. 화학과 학생들의 기말고사 성적을 성적순으로 검색한다. //같은 사람이 여러번 나오는데... 어떻게 하징... 평균내야하나...

SELECT major 학과, s.sno 학번, sname 이름, TO_CHAR(AVG(result), 90.99) 기말고사평균성적
FROM student s, score r, course c
WHERE major = '화학'
AND s.sno=r.sno AND r.cno=c.cno
GROUP BY major, s.sno, sname
ORDER BY TO_CHAR(AVG(result), 90.99) DESC;

학과    학번    이름       기말고사평균
------- ------- ---------- ------------
화학    915301  정동상      73.30
화학    925306  김재백      73.15
화학    905302  정욱상      72.85
화학    925305  황현정      72.63
화학    945303  남궁경아    70.86
화학    945314  이철윤      70.59
화학    915304  권보수      69.50


6. 학과별 기말고사 평균을 성적순으로 검색한다.

SELECT major 학과, TO_CHAR(AVG(result), 90.99) 기말고사평균
FROM student s, score r, course c
WHERE s.sno=r.sno AND r.cno=c.cno
GROUP BY major
ORDER BY TO_CHAR(AVG(result), 90.99) DESC;

학과    기말고사평균
------- ------------
식영     69.99
유공     69.56
화학     69.44
물리     68.92
생물     67.93


7. 30번 부서의 업무별 연봉의 평균을 검색한다.
(단 출력 양식은 소수이하 두 자리까지 통일된 형식으로 출력한다.)

SELECT dno 부서번호, job 업무,  TO_CHAR(AVG(sal*12+NVL(comm,0))) 평균연봉
FROM emp
WHERE dno = 30
GROUP BY dno, job;

부서번호  업무    평균연봉
--------- ------- -----------
30        모델링  51600
30        개발    39184


8. 물리학과 학생 중에 학년별로 성적이 가장 우수한 학생의 평점을 검색한다.

SELECT major 학과, syear 학년, TO_CHAR(MAX(avr), 90.99) 성적
FROM student
WHERE major = '물리'
GROUP BY major, syear
ORDER BY syear;

학과          학년 성적
------- ---------- ------------
물리             1   3.20
물리             2   3.22
물리             3   4.00
물리             4   3.33


9. 학년별로 환산 평점의 평균값을 검색한다.

(단 출력 양식은 소수이하 두 자리까지 통일된 양식으로 출력한다.)

SELECT syear 학년, TO_CHAR(AVG(avr*4.5/4), 90.99) 성적
FROM student
GROUP BY syear
ORDER BY syear;

      학년 성적
---------- ------------
         1   3.13
         2   2.97
         3   3.08
         4   2.85


10. 화학과 1학년 학생 중 평점이 평균 이하인 학생을 검색한다.

SELECT major 학과, syear 학년, sno 학번, sname 이름, TO_CHAR(avr, 90.99) 성적
FROM student
WHERE major='화학' AND syear=1
AND avr <= (SELECT AVG(avr) FROM student
WHERE major='화학' AND syear=1);

학과          학년 학번    이름       성적
------- ---------- ------- ---------- ------------
화학             1 945303  남궁경아     2.36
화학             1 945314  이철윤       2.22

 

+ Recent posts