/* **************************************************************************
집계(Aggregation) 함수와 GROUP BY, HAVING
************************************************************************** */
use hr;
/* ******************************************************************************************
집계함수, 그룹함수, 다중행 함수
- 인수(argument)는 컬럼.
- sum(): 전체합계
- avg(): 평균
- min(): 최소값
- max(): 최대값
- stddev(): 표준편차
- variance(): 분산
- count(): 개수
- 인수:
- 컬럼명: null을 제외한 값들의 개수.
- *: 총 행수 - null과 관계 없이 센다.
- count(distinct 컬럼명): 고유값의 개수.
- count(*) 를 제외한 모든 집계함수들은 null을 제외하고 집계한다.
- (avg, stddev, variance는 주의)
-avg(), variance(), stddev()은 전체 개수가 아니라 null을 제외한 값들의 평균, 분산, 표준편차값이 된다.=>avg(ifnull(컬럼, 0))
- 문자타입/일시타입: max(), min(), count()에만 사용가능
- 문자열 컬럼의 max(): 사전식 배열에서 가장 마지막 문자열, min()은 첫번째 문자열.
- 일시타입 컬럼은 오래된 값일 수록 작은 값이다.
편차 : 값이 평균으로부터 얼마나 떨어져있는지.
평균 : 10, value : '5'
표준편차 : 편차들의 평균
분사 ㅣ 표준편차의 제곱
******************************************************************************************* */
-- EMP 테이블에서 급여(salary)의 총합계, 평균, 최소값, 최대값, 표준편차, 분산, 총직원수를 조회
select sum(salary),
avg(salary),
min(salary),
max(salary),
stddev(salary),
variance(salary),
count(*),
count(emp_id)
from emp;
-- count(컬럼명) 그 컬럼에서 데이터개수(null이 아닌 값들)
select count(comm_pct) from emp;
select avg(comm_pct), -- null을 뺀 평균, 커미션을 받는 사람들 기준 평균.
avg(ifnull(comm_pct, 0)) -- 전체 직원 기준 평균.
from emp;
-- EMP 테이블에서 가장 최근 입사일(hire_date)과 가장 오래된 입사일을 조회
select max(hire_date),
min(hire_date)
from emp;
-- EMP 테이블의 부서(dept_name) 의 개수를 조회
select count(dept_name)
from emp;
-- EMP 테이블에서 job 종류의 개수 조회
select count(distinct job)
from emp;
group by 절 : 특정 컬럼(들)의 값별로 행들을 나누어 집계할 때 기준컬럼을 지정하는 구문
- 구문 : group by 컬럼명 [, 컬럼명]
- 컬럼 : 범주형 컬럼을 사용
- select의 where 절 다음에 기술
- select 절에는 group by에서 선언한 컬럼들만 집계함수와 같이 올 수 있다.
/* **************
group by 절
- 특정 컬럼(들)의 값별로 행들을 나누어 집계할 때 기준컬럼을 지정하는 구문.
- 예) 업무별 급여평균. 부서-업무별 급여 합계. 성별 나이평균
- 구문: group by 컬럼명 [, 컬럼명]
- 컬럼: 범주형 컬럼을 사용 - 부서별 급여 평균, 성별 급여 합계
- select의 where 절 다음에 기술한다.
- select 절에는 group by 에서 선언한 컬럼들만 집계함수와 같이 올 수 있다.
****************/
-- 업무(job)별 급여의 총합계, 평균, 최소값, 최대값, 표준편차, 분산, 직원수를 조회
select job,
sum(salary),
round(avg(salary), 2),
min(salary),
max(salary),
round(stddev(salary), 2),
round(variance(salary), 2),
count(*)
from emp
group by job;
-- 입사연도 별 직원들의 급여 평균.
select year(hire_date) 입사년도, avg(salary) 급여평균 from emp group by year(hire_date) order by 1;
-- 부서명(dept_name) 이 'Sales'이거나 'Purchasing' 인 직원들의 업무별 (job) 직원수를 조회
select job,
count(*) 직원수 -- 3. 집계
from emp -- 0. 테이블 선택.
where dept_name in ('Sales', 'Purchasing') -- 1. 조건이 True인 행을 조회
group by job; -- 2. job 별로 그룹을 나눈다.
-- 부서(dept_name), 업무(job) 별 최대, 평균급여(salary)를 조회.
select dept_name,
job,
max(salary),
avg(salary)
from emp
group by dept_name, job -- dept_name과 job이 같은 직원들이 같은 그룹으로 묶인다.
order by 1;
-- 급여(salary) 범위별 직원수를 출력. 급여 범위는 10000 미만, 10000이상 두 범주.
select case when salary < 10000 then "10000 미만"
else "10000 이상" end as "급여 범위",
count(*) as "직원수"
from emp
group by case when salary < 10000 then "10000 미만"
else "10000 이상" end ;
select case when salary < 10000 then 1
else 2 end
from emp;
having 절 : group by 로 나뉜 그룹을 filtering 하기 위한 조건을 정의하는 구문.
- group by 다음 order by 전에 온다.
- 구문 : having 제약 조건
- 연산자는 where절의 연산자를 사용한다.
- 피연산자는 집계함수(의 결과)
** where 절은 행을 filtering한다.
having 절은 group by 로 묶인 그룹들을 filtering 한다.
/* **************************************************************
having 절
- group by 로 나뉜 그룹을 filtering 하기 위한 조건을 정의하는 구문.
- group by 다음 order by 전에 온다.
- 구문
having 제약조건
- 연산자는 where절의 연산자를 사용한다.
- 피연산자는 집계함수(의 결과)
** where절은 행을 filtering한다.
having절은 group by 로 묶인 그룹들을 filtering한다.
************************************************************** */
-- 직원수가 10 이상인 부서의 부서명(dept_name)과 직원수를 조회
select dept_name 부서명,
count(*) 직원수
from emp
group by dept_name
having count(*) >= 10;
-- 직원수가 10명 이상인 부서의 부서명과 그 부서 직원들의 평균 급여를 조회.
select dept_name 부서명,
round(avg(salary), 2) as "평균 급여"
from emp
group by dept_name
having count(*) >= 10;
with rollup : group by로 묶어 집계할 때 총계나 중간 집계(group by 컬럼이 여러개일경우)를 계산
- group by 뒤에 붙인다.
- 구문 : group by 컬럼명[, ..] with rollup
grouping(컬럼명) : 컬럼명으로 나뉜 데이터들을 집계한 경우 0 반환, 아닌 경우 1을 반환 -> 1이 반환 된 경우는 그 행의 결과는 총계이거나 중간소계이다.
/* ***************************************************************************************
# with rollup : group by 뒤에 붙인다.
- group by로 묶어 집계할 때 총계나 중간 집계(group by 컬럼이 여러개일경우) 를 계산한다.
- 구문 : group by 컬럼명[, .. ] with rollup
- ex) group by job with rollup
# grouping(컬럼명 [, 컬럼명]) : select 절에서 사용.
- group by 컬럼명 with rollup 으로 집계했을 때 grouping(컬럼명)의 컬럼이 집계시 값들을 그룹으로 나누는데 사용되었으면 0 사용되지 않았으면 1을 반환한다.
1이 반환 된 경우는 그 행의 결과는 총계이거나 중간소계임을 말한다.
- grouping(컬럼1, 컬럼2, 컬럼3) 과 같이 여러개 컬럼을 지정한 경우
집계에 모든 세개의 컬럼이 다 사용되었으면 0
앞의 두개만 사용되었으면 1
앞의 한개만 사용되었으면 3
세개 다 사용되지 않았으면 7
컬럼1 컬럼2 컬럼3
2**2 + 2**1 + 2**0 각각 참여하면 0, 참여 안하면 1을 곱해서 더한다.
* ***************************************************************************************/
-- EMP 테이블에서 업무(job)별 급여(salary)의 평균과 평균의 총계도 같이나오도록 조회.
select ifnull(job, "총 평균") as "job", -- rollup으로 인해 평균의 총계가 나타난 값의 job이 null값이기에 총 평균으로 바꾼다.
round(avg(salary), 2) as "평균급여"
from emp
group by job with rollup;
-- EMP 테이블에서 부서(dept)별 급여(salary)의 평균과 평균의 총계도 같이나오도록 조회.
select -- dept_name 부서명,
if(grouping(dept_name) = 0, dept_name, '총평균') 부서명, -- 결과값에서 1이 나온경우 그 행의 결과가 총계이거나 중간소계이다.
round(avg(salary), 2) 평균급여
from emp
group by dept_name with rollup;
-- EMP 테이블에서 부서(dept_name), 업무(job) 별 salary의 합계와 직원수를 소계와 총계가 나오도록 조회
select dept_name 부서,
job 업무,
grouping(dept_name, job),
sum(salary) 급여합계,
count(*) 직원수
from emp
group by dept_name, job with rollup;
select case grouping(dept_name, job) when 0 then concat(ifnull(dept_name, '미배치'), '-', job)
when 1 then ifnull(dept_name, '미배치')
when 3 then '총계' end as '구분',
sum(salary) 급여합계,
count(*) 직원수
from emp
group by dept_name, job with rollup;'Data_Analysis_Track_33 > SQL' 카테고리의 다른 글
| SQL_05(JOIN) (0) | 2023.09.05 |
|---|---|
| SQL_05(Foreign key, JOIN 이론) (0) | 2023.09.05 |
| SQL_03(함수) (0) | 2023.09.01 |
| SQL_02(SELECT, WHERE) (0) | 2023.08.31 |
| SQL_01(테이블, SQL(DDL, DML, DCL)) (2) | 2023.08.30 |