1. GROUP BY
🍋 기준이 되는 필드를 뒤에 적어주면 기준 필드가 같은 레코드를 모아 통계값을 구함
🍋 GROUP BY 구문은 그룹핑을 해 줄 뿐이며 어떤 통계를 낼 것인가는 필드 목록의 집계 함수에 따라 달라짐
🍋 여러 개의 집계함수를 동시에 사용 가능
SELECT '영업부', AVG(salary) FROM tStaff WHERE depart='영업부';
SELECT '총무부', AVG(salary) FROM tStaff WHERE depart='총무부';
SELECT '인사과', AVG(salary) FROM tStaff WHERE depart='인사과';
📌 부서별 월급 평균을 알고 싶어 부서마다 AVG 함수를 호출하게 되면 부서 목록을 만들고 각 부서마다 명령을 일일이 실행해야 하고 결과도 따로 출력되어 보기도 불편하다. 또한, 집계함수와 일반필드를 같이 적을 수 없어 필드 목록에 부서명을 한 번 더 적어야 한다.
💡 이 경우에 필요한 구문이 GROUP BY. 기준 필드는 집계 함수와 같이 쓸 수 있어서 목록도 보기 좋게 출력 할 수 있음.
📌 부서별 월급 평균을 구하려면 depart 필드 기준으로 그룹핑
1) 기준 필드순으로 정렬하여 같은 그룹끼리 구분
2) 통계 대상 필드를 순서대로 읽어 집계를 구함
SELECT depart, AVG(salary) FROM tStaff GROUP BY depart;
SELECT grade, AVG(salary) FROM tStaff GROUP BY grade;
SELECT depart, COUNT(*), MAX(joindate), AVG(score) FROM tStaff GROUP BY depart;
2. 기준 필드
🍋 GROUP BY의 기준 필드는 중복 값이 있을 때만 의미있다.
➡️ 레코드별로 고유한 값을 가지는 필드는 그룹핑 기준으로 부적합(예 : 아이디)
➡️ 한 부서에서 여러 직원이 소속되어 있고 부서가 같은 직원이 많기 때문에 부서별 집계 가능.
➡️ 성별도 중복값이어서 그룹핑 필드로 적합
SELECT gender, AVG(salary) FROM tStaff GROUP BY gender;
📌 남녀 성별로 평균 월급을 구함. 성별은 남자, 여자 두 부류이며 그룹핑한 결과도 2개의 레코드로 출력
🔖 중복 값을 가지는 필드만 그룹핑의 기준이 되는 것은 아니며 임의의 필드를 기준으로 그룹핑 할 수 있다.
SELECT name, SUM(salary) FROM tStaff GROUP BY name;
📌 이름을 기준으로 그룹핑을 하는 것도 문법적으로 가능하지만 전 직원의 월급이 각각 출력이 되어 의미가 없음.
🔖 기준 필드를 콤마로 구분하여 두 개 이상도 쓸 수 있다.
➡️ 이 경우 첫 번째 기준으로 그룹을 나누고 그 그룹 내에서 다시 두 번째 기준으로 그룹을 나눈다.
🔖 기준 필드의 순서는 그룹핑 과정에 영향을 주지만 결과에는 영향을 미치지 않는다.
➡️ 순서는 ORDER BY로 조정 가능
SELECT depart, gender, COUNT(*) FROM tStaff GROUP BY depart, gender;
SELECT gender, depart, COUNT(*) FROM tStaff GROUP BY gender, depart;
SELECT depart, gender, COUNT(*) FROM tStaff GROUP BY depart, gender ORDER BY gender, depart;
📌 부서별, 성별로 그룹핑하여 직원수 구함. 총무부는 여직원이 없어서 5개의 그룹만 나옴.
3. GROUP BY의 필드 목록
⚡️ <그룹핑 쿼리의 기본 형식>
SELECT 기준필드, 집계함수() FROM 테이블 GROUP BY 기준필드;
🍋 GROUP BY 절이 있으면 필드 목록에는 기준 필드나 집계 함수만 와야 한다.
🍋 필드 목록의 제일 처음에는 통상 기준 필드를 출력하여 어떤 그룹에 대한 통계인지 표시
➡️ 기준 필드를 빼고 집계 함수만으로 쿼리를 구성하면, 계산은 똑바로 됐지만 각 행이 어떤 부서에 대한 통계치인지 알아 볼 수 없다.
SELECT depart, salary FROM tStaff GROUP BY depart;
SELECT SUM (salary) FROM tStaff GROUP BY depart;
🍋 집계 함수는 다중 값이 있어야 계산할 수 있으므로 그룹핑을 할 때만 유용
➡️ GROUP BY 절 없이 일반 필드와 집계 함수를 같이 출력하면 의미가 없다
SELECT depart, SUM(salary) FROM tStaff;
📌 레코드별로 고유한 부서명과 통계에 의해 계산하는 월급 총합은 같이 출력할 수 있는 값이 아니라서
이 명령은 다음 둘 중에 하나로 수정하는게 적당.
📌 뒤에 GROUP BY 절을 붙여 부서별로 그룹핑하면 기준 필드인 부서명도 출력할 수 있고
부서의 월급 총합을 구하는 SUM 함수도 사용할 수 있다.
SELECT depart, SUM(salary) FROM tStaff GROUP BY depart;
SELECT SUM(salary) FROM tStaff;
4. HAVING
// 위치 순서
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY
🍋 HAVING은 GROUP BY 다음에 오며 통계 결과 중 출력할 그룹의 조건을 지정 (즉 HAVING은 GROUP BY 문의 조건절)
📌 부서별 평균 월급을 출력하는 명령은 별다른 조건이 없으면 모든 부서의 평균 월급을 출력.
평균 월급이 340을 넘는 부서만 출력하고 싶다면 GROUP BY 다음에 HAVIING 절을 추가.
SELECT depart, AVG(salary) FROM tStaff GROUP BY depart HAVING AVG(salary) >= 340;
📌 그룹별 통계를 뽑고 그 결과셋에서 HAVING 조건에 맞는 레코드만 출력.
평균 월급이 327인 인사과는 제외.
🍋 출력 순서를 지정할 때는 ORDER BY 절을 뒤에 붙인다.
🍋 GROUP BY 다음에 HAVING이 오고 ORDER BY는 항상 제일 마지막에 위치한다.
SELECT depart, AVG(salary) FROM tStaff
GROUP BY depart HAVING AVG(salary) >= 340
ORDER BY AVG(salary) DESC;
🍋 WHERE 와 HAVING은 적용 시점과 제한 대상이 다르다.
🍋 WHERE 절은 GROUP BY 앞에 나타나며 통계 대상 레코드의 조건을 제한한다.
SELECT depart, AVG(salary) FROM tStaff WHERE salary > 300 GROUP BY depart;
📌 월급 300 초과 조건에 의해 월급 300 이하의 직원은 평균에서 아예 제외되어 평균값이 더 높게 나타남. 만약 모든 직원의 월급이 300 이하이면 이 부서는 아예 결과셋에 나타나지고 않음.
🍋 HAVING 절은 GROUP BY 다음에 나타나며 집계한 결과셋의 조건을 제한한다.
SELECT depart, AVG(salary) FROM tStaff WHERE salary > 300 GROUP BY depart
HAVING AVG(salary) >= 360 ORDER BY depart;
📌 월급이 300 초과인 직원들을 대상으로 부서별 평균 월급을 구하고 그 결과 평균 월급이 360 이상인 부서만 고른 후 부서명으로 정렬
⚡️ 처리순서
1. WHERE 절이 직원목록에서 월급 300이하의 직원을 먼저 제거
2. 부서별로 그룹핑하여 AVG 함수로 남은 직원의 부서별 평균 월급을 계산
3. HAVING 절에 의해 평균 월급이 낮은 부서는 제외
4. 남은 부서를 ORDER BY가 정렬하여 출력
SELECT depart, MAX(salary) FROM tStaff WHERE depart IN ('인사과', '영업부') GROUP BY depart;
SELECT depart, MAX(salary) FROM tStaff GROUP BY depart HAVING depart IN ('인사과', '영업부');
📌 두 쿼리 모두 인사과와 영업부의 최대 월급을 조사.
📌 조건을 적용하는 시점은 다르지만 조건의 내용은 같아 최종 실행 결과는 같음.
💡 내부적인 실행 과정은 차이가 있음
1. WHERE 절은 집계전에 총무부를 제외하여 꼭 필요한 계산만 함.
2. HAVING 절은 모든 부서의 집계를 다 끝낸 후 총무부를 제거하는 식이라 출력하지도 않을 총무부의 집계까지 계산하여 비효율적
[ 내용 참고 ; IT 학원 강의 ]
'Database > MySQL' 카테고리의 다른 글
[MySQL] DELETE 문 (1) | 2024.02.24 |
---|---|
[MySQL] INSERT 문 (0) | 2024.02.23 |
[MySQL] 집계 함수 (aggregate function) (0) | 2024.02.23 |
[MySQL] SELECT문 | ORDER BY, DISTINCT, LIMIT, OFFSET FETCH (0) | 2024.02.23 |
[MySQL] SELECT문 | WHERE, NULL, 논리연산자, LIKE, BETWEEN, IN (0) | 2024.02.23 |