코딩 공부/DataBase

[DataBase] 07_그룹함수와 그룹조회

chocbi 2020. 5. 11. 15:14

그룹함수와 그룹조회

#01. 그룹함수

  • 그룹 함수란?
    • 그룹함수는 테이블의 전체 행을, 하나 이상의 칼럼을 기준으로 칼럼 값에 따라 그룹화하여 그룹별로 결과를 출력하는 함수이다.
종류 설명
COUNT 행의 갯수 출력
MAX NULL을 제외한 모든행에서 최대값 출력
MIN NULL을 제외한 모든 행에서 최소값 출력
SUM NULL을 제외한 모든 행의 합계
AVG NULL을 제외한 모든 행의 평균값

예제1

  • 3학년 학생은 총 몇 명인가?
mysql> select count(studno) from student where grade = '3';
+---------------+
| count(studno) |
+---------------+
|             2 |
+---------------+

예제2

-101번 학과에 소속된 교수들의 보직 수당 조회

mysql> select comm from professor where deptno = 101;
+------+
| comm |
+------+
|   20 |
|   15 |
| NULL |
| NULL |
+------+

예제3

  • 101 학과에 소속된 교수들 중에서 보직수당을 받는 교수의 수를 조회하시오.
    • COUNT 함수는 지정된 컬럼에서 NULL 데이터는 제외하고 집계하기 때문에, 보직수당이 결정되지 않은 교수는 집계에서 제외된다.
mysql> select count(comm) from professor where deptno = 101;
+-------------+
| count(comm) |
+-------------+
|           2 |
+-------------+

예제4

  • 101 학과에 소속된 교수는 모두 몇 명인가?
    • 전체 데이터수를 조회하기 위해서는 COUNT 함수에 '*'을 지정하거나 NULL 데이터가 저장되어 있지 않은 컬럼을 지정한다.
    • 일반적으로 NULL이 저장되지 않는 컬럼을 지정하는 것이 처리속도가 더 빠르다.
mysql> select count(*) from professor where deptno = 101;
+----------+
| count(*) |
+----------+
|        4 |
+----------+

예제5

  • 급여를 가장 많이 받는 교수는 얼마를 받는가?
mysql> select max(sal) from professor;
+----------+
| max(sal) |
+----------+
|      500 |
+----------+

예제6

  • 급여를 가장 적게 받는 교수는 얼마를 받는가?
mysql> select MIN(sal) from professor;
+----------+
| MIN(sal) |
+----------+
|      210 |
+----------+

예제7

  • 한달에 지급되는 교수의 급여는 모두 얼마인가?
mysql> select sum(sal) from professor;
+----------+
| sum(sal) |
+----------+
|     2900 |
+----------+

예제8

-학생들의 평균 키는 얼마인가?

mysql> select avg(height) from student;
+-------------+
| avg(height) |
+-------------+
|    171.5625 |
+-------------+

예제9

  • 101번 학과 학생들의 몸무게 평균과 합계를 출력하시오.
mysql> select avg(weight), sum(weight) from student where deptno=101;
+-------------+-------------+
| avg(weight) | sum(weight) |
+-------------+-------------+
|     68.0000 |         544 |
+-------------+-------------+

#02. 그룹조회

1) GROUP BY 절

​ -특정 칼럼 값을 기준으로 테이블의 전체 행을 그룹별로 나누기 위한 절.

select { 컬럼이름 [ as 별칭] ..., 그룹함수(컬럼명)} from <테이블이름>
[ where 검색조건]
[ group by 컬럼이름 ]
[ order by 컬럼이름 [정렬옵션] ]
    - 그룹핑 전에 WHERE절을 사용하여 그룹 대상 집합을 머저 선택가능.
    - GROUP BY 절에는 반드시 칼럼이름이 포함되어야 하며 별명 사용 불가
    - SELECT 절에서 집계 함수 없이 나열된 칼럼 이름이나 표현식은 GROUP BY절에 반드시 포함되어야 함.
    - GROUP BY 절에 나열된 칼럼 이름은 SELECT 절에 명시하지 않아도 됨.
    - SELECT 절에서 그룹함수를 사용할 경우 group by 절에서 나눈 그룹 안에서 집계를 수행한다.

2) 그룹조회와 집계 함수의 관계

mysql> select deptno, name from professor order by deptno;
+--------+--------+
| deptno | name   |
+--------+--------+
|    101 | 김도훈 |
|    101 | 성연희 |
|    101 | 이만식 |
|    101 | 전은지 |
|    102 | 염일웅 |
|    102 | 권혁일 |
|    201 | 이재우 |
|    202 | 남은혁 |
+--------+--------+
  • 학과 번호로 그룹을 형성하면 교수의 이름을 어떻게 처리 해야할까?
mysql> select deptno, name from professor group by deptno;
// 오류가 일어난다. 과목코드로 묶어야하는 이름이 여러개여서 오류가 난다.
  • group by 절에 명시되지 않은 컬럼을 SELECT에서 사용할 경우에는 집계함수를 사용하여 각 그룹별 통계 데이터를 얻을 수 있다.
mysql> select deptno, count(name) from professor group by deptno;
+--------+-------------+
| deptno | count(name) |
+--------+-------------+
|    101 |           4 |
|    102 |           2 |
|    201 |           1 |
|    202 |           1 |
+--------+-------------+

예제1

  • 교수 테이블에서 학과별로 교수 수와 보직 수당을 받는 교수 수를 출력하시오.
mysql> select deptno, count(*), count(comm)
    -> from professor
    -> group by deptno;
+--------+----------+-------------+
| deptno | count(*) | count(comm) |
+--------+----------+-------------+
|    101 |        4 |           2 |
|    102 |        2 |           1 |
|    201 |        1 |           0 |
|    202 |        1 |           1 |
+--------+----------+-------------+

3) 다중 칼럼을 이용한 그룹별 검색

  • GROUP BY 절에서 두 개 이상의 컬럼을 콤마(,)로 구분하여 명시할 경우 첫번째 컬럼에 대한 그룹을 형성하고, 각 그룹 안에서 두 번째 컬럼에 대한 2차 그룹을 형성한다.
select { 칼럼이름 [ as 별칭] ..., 그룹함수(컬럼명)} from <테이블이름>
[where 검색조건]
[group by 컬럼1이름, 컬럼2이름, ... , 컬럼n이름 ]
[order by 컬럼이름 [정렬옵션] ]

예제1

  • 학생 테이블에서 전체 학생을 소속 학과별로 나누고, 같은 학과 학생은 다시 학년별로 그룹핑하여, 학과와 학년별로 인원수, 평균 몸무게를 출력
mysql> select deptno, grade, count(*), avg(weight)
    -> from student
    -> group by deptno, grade;
+--------+-------+----------+-------------+
| deptno | grade | count(*) | avg(weight) |
+--------+-------+----------+-------------+
|    101 |     4 |        2 |     82.0000 |
|    101 |     1 |        2 |     62.0000 |
|    101 |     3 |        1 |     88.0000 |
|    101 |     2 |        3 |     56.0000 |
|    102 |     2 |        1 |     48.0000 |
|    102 |     4 |        1 |     92.0000 |
|    102 |     1 |        1 |     68.0000 |
|    102 |     3 |        1 |     70.0000 |
|    201 |     1 |        3 |     65.3333 |
|    201 |     2 |        1 |     51.0000 |
+--------+-------+----------+-------------+

#03. 집계결과에 대한 조건 지정

1) HAVING절

  • SELECT 명령문의 WHERE절과 비슷한 기능을 하는 것으로 GROUP BY절에서 조건 검색을 할 경우 반드시 HAVING 절을 사용해야 한다.
select {컬럼이름 [ as 별칭]..., 그룹함수(컬럼명)} from <테이블이름>
[where 검색조건]
[group by 컬럼1이름, 컬럼2이름, ... , 컬럼n이름 ]
[having 검색조건 ]
[order by 컬럼이름 [정렬옵션] ]

2) HAVING절을 사용해야 하는 경우

  • 집계 함수에 대한 검색 조건을 지정하고자 할 경우에는 GROUP BY 절 뒤에 HAVING절을 사용해야 한다.
    • count(*)의 결과가 4보다 큰 데이터만 조회되었다.
mysql> select grade, count(*), avg(height) avg_height, AVG(weight) avg_weight
    -> from student
    -> group by grade
    -> having count(*) > 4
    -> order by avg_height desc;
+-------+----------+------------+------------+
| grade | count(*) | avg_height | avg_weight |
+-------+----------+------------+------------+
|     1 |        6 |   175.3333 |    64.6667 |
|     2 |        5 |   164.8000 |    53.4000 |
+-------+----------+------------+------------+

예제1

  • 동일 학과 내에서 같은 학년에 재학중인 학생 수가 3명이상인 그룹의 학과 번호, 학년, 학생 수, 최대 키, 최대 몸무게를 출력하세요.
mysql> select deptno, grade, count(*), max(height), max(weight)
    -> from student
    -> group by deptno, grade
    -> having count(*) >= 3
    -> order by deptno;
+--------+-------+----------+-------------+-------------+
| deptno | grade | count(*) | max(height) | max(weight) |
+--------+-------+----------+-------------+-------------+
|    101 |     2 |        3 |         171 |          72 |
|    201 |     1 |        3 |         184 |          70 |
+--------+-------+----------+-------------+-------------+
2 rows in set (0.01 sec)

#### 연습문제

  • 101번 학과 학생들 중에서 최대 키와 최소키를 출력하여라.
mysql> select max(height), max(weight)
    -> from student
    -> where deptno = '101';
+-------------+-------------+
| max(height) | max(weight) |
+-------------+-------------+
|         186 |          92 |
+-------------+-------------+
  • 학과별로 소속 교수들의 평균 급여, 최소 급여, 최대 급여를 출력하여라.
mysql> select avg(sal), min(sal), max(sal)
    -> from professor
    -> group by deptno;
+----------+----------+----------+
| avg(sal) | min(sal) | max(sal) |
+----------+----------+----------+
| 372.5000 |      210 |      500 |
| 345.0000 |      240 |      450 |
| 320.0000 |      320 |      320 |
| 400.0000 |      400 |      400 |
+----------+----------+----------+
  • 학과별로 평균 몸무게와 학생수를 출력하되 평균 몸무게의 내림차순으로 정렬하세요.
mysql> select avg(weight), count(*)
    -> from student
    -> group by deptno
    -> order by avg(weight) desc;
+-------------+----------+
| avg(weight) | count(*) |
+-------------+----------+
|     69.5000 |        4 |
|     68.0000 |        8 |
|     61.7500 |        4 |
+-------------+----------+
  • 학과별 교수 수가 2명 이하인 학과의 학과 번호, 교수 수를 출력하세요.
mysql> select deptno, count(*)
    -> from professor
    -> group by deptno
    -> having count(*) <= 2;
+--------+----------+
| deptno | count(*) |
+--------+----------+
|    102 |        2 |
|    201 |        1 |
|    202 |        1 |
+--------+----------+