그룹화(Grouping)

Joy🌱·2023년 1월 12일
0

🐚 Oracle

목록 보기
3/11
post-thumbnail

💁‍♀️ 그룹화(Grouping)란,
데이터를 그룹화하는 것, 즉 데이터를 집계하는 것으로써 단 한 개의 결과값만 산출하는 그룹함수를 이용하여 여러 개의 결과값을 산출하기 위해 사용


📍 작성하는 절들의 순서 및 작동되는 우선 순위
FROM이 가장 먼저 작동 후, ORDER BY가 가장 마지막으로 실행됨

[ 5 ] SELECT 컬럼명 AS 별칭, 계산식, 함수식
[ 1 ] FROM 참조할 테이블명
[ 2 ] WHERE 컬럼명 or 함수식 비교 연산자 비교값
[ 3 ] GROUP BY 그룹을 묶을 컬럼명
[ 4 ] HAVING 그룹함수식 비교연산자 비교값
[ 6 ] ORDER BY 컬럼명 or 별칭 or 컬럼순법 정렬방식 [NULL FIRST or LAST]

👀 ORDER BY절

ORDER BY 컬럼명 or 별칭 or 컬럼순번 정렬방식 NULLS FIRST or LAST

💁‍♀️ ORDER BY절이란,
SELECT한 컬럼에 대해 정렬을 할 때 작성하는 구문

  • SELECT 구문의 가장 마지막에 작성하며, 실행순서도 가장 마지막에 수행

👀 GROUP BY절

GROUP BY 컬럼명 or 함수식, ...

💁‍♀️ GROUP BY절이란,
같은 값들이 여러 개 기록된 컬럼을 가지고 같은 값들을 하나의 그룹으로 묶는 절

  • 그룹함수를 이용하여 여러 개의 결과값을 산출하기 위해서 그룹함수가 적용될 그룹의 기준을 GROUP BY절에 기술하여 사용
  • 그룹으로 묶은 값에 대해서 SELECT 절에서 그룹 함수의 사용을 가능하게 함

1) DETP_CODE 기준으로 그룹화

SELECT
        COUNT(*)	>>> NULL을 포함한 전체 행 갯수 리턴
    ,   DEPT_CODE
    FROM EMPLOYEE
GROUP BY DEPT_CODE;
				>>> DEPT_CODE로 그룹화하면 부서당 몇명의 인원이 있는지 카운팅 가능 
                >>> (부서코드가 같은 것끼리 그룹화 후, 그것의 갯수를 COUNT)
              	>>> 그룹화 하지 않았을 경우, 그룹 함수인 COUNT 사용 불가

◼ 부서별 급여 합계, 평균(정수처리), 인원수 조회 후 부서코드 순 오름차순 정렬

SELECT
        DEPT_CODE 부서
    ,   SUM(SALARY) 합계
    ,   ROUND(AVG(SALARY)) 평균
    ,   COUNT(*) 인원수
    FROM EMPLOYEE
GROUP BY DEPT_CODE
ORDER BY DEPT_CODE;
/* ORDER BY 부서; */
/* ORDER BY 1; */ >>> 부서를 의미
/* ORDER BY 1 DESC; */ >>> 거꾸로(내림차순)
/* ORDER BY 1 DESC NULLS LAST; */ >>> 내림차순 및 NULL을 가장 마지막으로

📌 Ref.
ORDER BY 컬럼명 or 별칭 or 컬럼순번 정렬방식 NULLS FIRST or LAST

◼ 직급 코드별로 보너스를 받는 사원수를 조회하고 직급 코드 오름차순 정렬

SELECT
        JOB_CODE
    ,   COUNT(BONUS) >>> NULL값을 가진 행 제외하고 조회
    FROM EMPLOYEE
GROUP BY JOB_CODE
ORDER BY JOB_CODE;

◼ 직급 코드별로 보너스를 받는 사원수를 조회하고 직급 코드 오름차순 정렬 (단, 보너스를 받는 사람이 없는 직급 코드의 경우 RESULT SET에서 제외)

SELECT
        JOB_CODE
    ,   COUNT(BONUS) 
    FROM EMPLOYEE
WHERE BONUS IS NOT NULL		>>> WHERE(조건)로 그룹화 전 미리 안받는 사람을 빼둠
GROUP BY JOB_CODE
ORDER BY JOB_CODE;

2) GROUP BY절에 하나 이상의 그룹 지정 가능

◼ DEPT_CODE, JOB_CODE 기준으로 그룹화

SELECT
        DEPT_CODE
    ,   JOB_CODE
    ,   SUM(SALARY)
    ,   COUNT(*)	>>> 해당 부서에서 해당 직급을 가지고 있는 사람들을 COUNT (중복 그룹)
	FROM EMPLOYEE
GROUP BY DEPT_CODE
	,    JOB_CODE
ORDER BY 1;

3) GROUP BY절에 함수식

◼ 성별 그룹으로 급여 평균(정수 처리), 합계, 인원수를 조회한 뒤 인원수로 내림차순 정렬

SELECT
        DECODE(SUBSTR(EMP_NO, 8, 1), '1', '남', '2', '여') 성별
    ,   ROUND(AVG(SALARY)) 평균
    ,   SUM(SALARY) 합계
    ,   COUNT(*) 인원수
    FROM EMPLOYEE
GROUP BY DECODE(SUBSTR(EMP_NO, 8, 1), '1', '남', '2', '여') >>> 식을 그대로 넣을 수 있음
--GROUP BY 성별 
ORDER BY 인원수 DESC;

📌 Ref.

* GROUP BY절이 SELECT절보다 우선 실행되기 때문에 별칭을 GROUP BY에 넣어 사용 불가 (GROUP BY절 실행 시점에 별칭은 생성되기 전)
* ORDER BY절은 가장 마지막 실행순서이므로 SELECT절의 별칭 사용 가능

👀 HAVING절

HAVING 컬럼명 or 함수식 비교연산자 비교값

💁‍♀️ HAVING절이란,
그룹 함수로 구해올 그룹에 대해 조건을 설정할 때 사용하는 절

  • WHERE절의 조건 설정은 그룹함수에서 사용 불가

1) WHERE절, HAVING절의 차이

◼ 300만원 이상의 월급을 받는 사원들을 대상으로 부서별 월급 평균 계산 (WHERE절 사용 케이스)

SELECT
        DETP_CODE
    ,   ROUND(AVG(SALARY)) 평균
    FROM EMPLOYEE
   WHERE SALARY >= 3000000		>>> 일단 WHERE절로 300만원 이하 월급의 직원은 필터링
GROUP BY DEPT_CODE
ORDER BY 1;

◼ 모든 직원을 대상으로 부서별 월급 평균을 구한 뒤 평균이 300만원 이상인 부서 조회 (HAVING절 사용 케이스)

SELECT
        DETP_CODE
    ,   ROUND(AVG(SALARY)) 평균
    FROM EMPLOYEE
GROUP BY DEPT_CODE
HAVING ROUND(AVG(SALARY)) >= 3000000	>>> 월급 평균이 300만원 이상인 부서 조회 (그룹에 대해 조건걸기)
ORDER BY 1;

👀 ROLLUP & CUBE (집계함수)

💁‍♀️ 집계함수란,
그룹별로 중간 집계 처리를 하는 함수로써, ROLLUPCUBE가 있음

  • 그룹 별로 묶인 값에 대한 중간 집계와 총 집계를 구할 때 사용
  • GROUP BY절에서만 사용

1) ROLLUP & CUBE

◼ ROLLUP

SELECT
        JOB_CODE
    ,   SUM(SALARY)
    FROM EMPLOYEE
GROUP BY ROLLUP(JOB_CODE)	>>> GROUP BY절 앞에서 사용
ORDER BY 1;

◼ CUBE

SELECT
        JOB_CODE
    ,   SUM(SALARY)
    FROM EMPLOYEE
GROUP BY CUBE(JOB_CODE)		>>> GROUP BY절 앞에서 사용
ORDER BY 1;

📌 Ref.

* 그룹화한 그룹이 1개일 경우, ROLLUP과 CUBE의 결과는 '동일'

2) ROLLUP & CUBE의 차이점

💁‍♀️ ROLLUP 함수는,
인자로 전달한 그룹 중 가장 먼저인 그룹의 그룹별 합계와 총 합계를 구하는 함수

SELECT
        DEPT_CODE
    ,   JOB_CODE
    ,   SUM(SALARY)
    FROM EMPLOYEE
GROUP BY ROLLUP(DEPT_CODE, JOB_CODE)	>>> 각 부서코드별 중간 합계가 나오고 총 합계 출력
ORDER BY 1;    

💁‍♀️ CUBE 함수는,
그룹으로 지정된 모든 그룹에 대한 중간 집계와 총 합계를 구하는 함수

SELECT
        DEPT_CODE
    ,   JOB_CODE
    ,   SUM(SALARY)
    FROM EMPLOYEE
GROUP BY CUBE(DEPT_CODE, JOB_CODE)	>>> 전달되는 모든 인자의 중간 집계 출력 
ORDER BY 1;							>>> (두 번째 인자인 JOB_CODE의 중간 집계도 출력)

👀 GROUPING 함수

GROUPING(컬럼명) : 이 컬럼으로 그룹화 되어있는지 확인 (되어있으면 0, 아니면 1 반환)

💁‍♀️ GROUPING 함수란,
ROLLUP이나 CUBE에 의한 산출물이 인자로 전달받은 컬럼 집합의 산출물이면 0을 반환하고, 아니면 1을 반환하는 함수


1) GROUPING 함수로 그룹화 확인

SELECT
        DEPT_CODE
    ,   JOB_CODE
    ,   SUM(SALARY)
    ,   COUNT(*)
    ,   GROUPING(DEPT_CODE) "부서별 그룹 묶인 상태" 
    ,   GROUPING(JOB_CODE) "직급별 그룹 묶인 상태"
    FROM EMPLOYEE
GROUP BY CUBE(DEPT_CODE, JOB_CODE)	>>> 이들 중, NULL값을 가진 행은 그룹으로 묶이지 않아 1 반환
ORDER BY 1;
										

2) GROUPING 함수의 활용

SELECT
       NVL(DEPT_CODE, '부서없음')	>>> : DEPT_CODE의 값이 NULL일 경우(부서가 없을 경우) '부서없음' 출력
     , JOB_CODE
     , SUM(SALARY)
     , CASE
         WHEN GROUPING(NVL(DEPT_CODE, '부서없음')) = 0 AND GROUPING(JOB_CODE) = 1 THEN '부서별합계'
         WHEN GROUPING(NVL(DEPT_CODE, '부서없음')) = 1 AND GROUPING(JOB_CODE) = 0 THEN '직급별합계'
         WHEN GROUPING(NVL(DEPT_CODE, '부서없음')) = 0 AND GROUPING(JOB_CODE) = 0 THEN '그룹별합계'
         ELSE '총합계'
       END 구분
	FROM EMPLOYEE
GROUP BY CUBE(NVL(DEPT_CODE, '부서없음'), JOB_CODE)
ORDER BY 1;

👀 SET OPERATION (집합 연산)

💁‍♀️ SET OPERATION이란,
여러 개의 SELECT 결과물을 하나의 쿼리로 만드는 연산자


📍 SET OPERATION의 종류

1) UNION
2) UNIONALL
3) INTERSECT
4) MINUS

1) UNION

💁‍♀️ UNION은,
여러 개의 쿼리를 하나로 합치는 연산자

  • 중복 된 영역을 제외하여 하나로 합침
SELECT
        EMP_ID
    ,   EMP_NAME
    ,   DEPT_CODE
    ,   SALARY
    FROM EMPLOYEE
   WHERE DEPT_CODE = 'D5'	>>> 세미콜론 제거 후 UNION 추가
   
   UNION	>>> 위 아래 SELECT절의 중복되는 값 2개를 제거하고 출력 
   
SELECT
        EMP_ID
    ,   EMP_NAME
    ,   DEPT_CODE
    ,   SALARY
    FROM EMPLOYEE
   WHERE SALARY > 3000000;

2) UNION ALL

💁‍♀️ UNION ALL은,
여러 개의 쿼리를 하나로 합치는 연산자

  • UNION과는 달리, 중복 영역을 모두 포함시킴
SELECT
        EMP_ID
    ,   EMP_NAME
    ,   DEPT_CODE
    ,   SALARY
    FROM EMPLOYEE
   WHERE DEPT_CODE = 'D5'	>>> 세미콜론 제거 후 UNION ALL추가
    
    UNION ALL	>>> 위 아래 SELECT절을 모두 출력 
    
SELECT
        EMP_ID
    ,   EMP_NAME
    ,   DEPT_CODE
    ,   SALARY
    FROM EMPLOYEE
   WHERE SALARY > 3000000;

3) INTERSECT

💁‍♀️ INTERSECT는,
여러 개의 SELECT한 결과에서 공통 부분만 결과로 추출

  • 수학에서의 교집합과 유사
SELECT
        EMP_ID
    ,   EMP_NAME
    ,   DEPT_CODE
    ,   SALARY
    FROM EMPLOYEE
   WHERE DEPT_CODE = 'D5'	>>> 세미콜론 제거 후 INTERSECT추가
    
    INTERSECT  >>> 위 아래 SELECT절에서 중복되는 값들만을 출력 
    
SELECT
        EMP_ID
    ,   EMP_NAME
    ,   DEPT_CODE
    ,   SALARY
    FROM EMPLOYEE
   WHERE SALARY > 3000000;

4) MINUS

💁‍♀️ MINUS는,
선행 SELECT 결과에서 후행 SELECT 결과와 겹치는 부분을 제외한 나머지만 추출

  • 수학에서의 차집합과 유사
SELECT
        EMP_ID
    ,   EMP_NAME
    ,   DEPT_CODE
    ,   SALARY
    FROM EMPLOYEE
   WHERE DEPT_CODE = 'D5'	>>> 세미콜론 제거 후 MINUS추가
    
    MINUS	>>>SELECT절에서 아래 SELECT절과 겹치는 부분을 제외하고 출력
    
SELECT
        EMP_ID
    ,   EMP_NAME
    ,   DEPT_CODE
    ,   SALARY
    FROM EMPLOYEE
   WHERE SALARY > 3000000;

👉 GROUPING SETS

💁‍♀️ GROUPING SETS는,
그룹별로 처리된 여러 개의 SELECT문을 하나로 합칠 때 사용하며, SET OPERATION과 결과 동일

SELECT
        DEPT_CODE
    ,   JOB_CODE
    ,   MANAGER_ID
    ,   FLOOR(AVG(SALARY))
    FROM EMPLOYEE
GROUP BY GROUPING SETS((DEPT_CODE, JOB_CODE, MANAGER_ID)
                        ,  (DEPT_CODE, MANAGER_ID)
                        ,  (JOB_CODE, MANAGER_ID)
                      );							>>> 1, 2, 3 그룹들 합치기

profile
Tiny little habits make me

0개의 댓글