IT STUDY LOG

[Oracle] 그룹 함수 기본 본문

computer science/database

[Oracle] 그룹 함수 기본

roheerumi 2023. 8. 30. 16:55

# 그룹함수

  • 집계 함수
  • 집계란 하나 이상의 데이터를 대상으로 한 일종의 통계정보
  • 단일 행 함수와 달리 전체 집합, 그룹으로 분류된 집합에 작용
  • DISTINCT  지정 시 중복되지 않은 값만 검토하고 ALL을 지정하면 중복값 포함 
  • 인자의 개수가 하나
  • 소그룹을 지을 경우 GROUP BY 절을 써주어야 함

 

그룹함수의 동작 방식

- 건건이 결과를 보여주는 것이 아닌 여러 행의 연산 결과를 하나로 보여줌 

 

#  그룹 함수 종류 

SELECT COUNT(sal), SUM(sal), AVG(sal), MIN(sal), MAX(sal)
  FROM emp;

SELECT COUNT(comm), SUM(comm), AVG(comm), MIN(comm), MAX(comm)
  FROM emp;

  

COUNT  예시

- COUNT(*) : NULL값을 포함한 행의 수 출력 (그룹함수 중 유일하게 널 포함 처리) 

- COUNT(표현식) : 표현식의 값이 NULL값인 것을 제외한 행의 수 출력

SELECT COUNT(*) 
  FROM emp
  WHERE deptno = 30
  AND   sal > 1000;

SELECT deptno, COUNT(*)
  FROM emp
  GROUP BY deptno;

 - HAVING의 위치는 GROUP BY 앞에 쓸 수 있으나 권장하지 않음 

SELECT deptno, COUNT(deptno) "직원수"
  FROM emp
  HAVING COUNT(deptno) >= 1
  GROUP BY deptno
  ORDER BY "직원수" DESC;

SELECT deptno, COUNT(*) "직원수"
  FROM emp
  GROUP BY deptno
  HAVING COUNT(*) >= 1
  ORDER BY deptno;

 - SELECT 구문의 해석 순서는, FROM절 > WHERE절 > GROUP BY절 > HAVING절 > SELECT절 > ORDER BY절 순

SELECT deptno, COUNT(*) "직원수" -- ⑤
  FROM emp                      -- ①
  WHERE sal > 2000              -- ②
  GROUP BY deptno               -- ③ 
  HAVING COUNT(deptno) >= 1     -- ④
  ORDER BY deptno;              -- ⑥

 - WHERE와 HAVING 사용시 결과 값은 동일하나 HAVING에 조건을 사용할 경우 불필요한 그룹핑이 선행되므로 비권장 

SELECT deptno, COUNT(*) "직원수"
  FROM emp
  WHERE deptno <= 20
  GROUP BY deptno, job
  HAVING COUNT(deptno) >= 2
  ORDER BY deptno, job;

SELECT deptno, COUNT(*) "직원수"
  FROM emp
  GROUP BY deptno, job
  HAVING COUNT(deptno) >= 2
         AND deptno <= 20
  ORDER BY deptno, job;

 - 아래 SELECT문은 실행할 수 없음 

SELECT deptno, AVG(sal)
  FROM emp
  GROUP BY deptno
  HAVING AVG(sal) > 1000
         AND job = 'CELRK'; -- WHERE절은 테이블 전체를 읽으므로 SELECT문에 없는 컬럼 또한 조건에 사용할 수 있으나 HAVING의 경우 그룹으로 묶은 컬럼과 집계함수만 조건에 사용할 수 있음

         

#  연습문제 

사원의 총수와 1980년, 1981년, 1982년, 1983년에 입사한 사원수를 표시 
-- 총 사원 수
SELECT COUNT(*)
  FROM emp;

-- 1980년도에 입사한 사원 수
SELECT COUNT(*)
  FROM emp
  WHERE TO_CHAR(hiredate, 'yyyy') = '1980';
  --  WHERE hiredate >= TO_DATE('1980/01/01', 'yyyy/mm/dd')
  --  AND hiredate < TO_DATE('1981/01/01', 'yyyy/mm/dd');

-- (방법1) COUNT 함수 + DECODE 함수
SELECT COUNT(*) "총 사원 수" -- 행이 존재하면 count 컬럼의 수를 1증가시킴
  , COUNT(DECODE(TO_CHAR(hiredate, 'yyyy'), '1980', 1
                                           , 0)) "NULL이 아니면 COUNT함"
  , COUNT(DECODE(TO_CHAR(hiredate, 'yyyy'), '1980', 'a'
                                         , NULL)) "1980년"
  , COUNT(DECODE(TO_CHAR(hiredate, 'yyyy'), '1981', 'a')) "1981년"
  , COUNT(DECODE(TO_CHAR(hiredate, 'yyyy'), '1982', 'a')) "1982년"
  , COUNT(DECODE(TO_CHAR(hiredate, 'yyyy'), '1983', 'a')) "1983년"
  FROM emp;

-- (방법2) SUM 함수 + CASE 함수
SELECT SUM(1) "총 사원 수"
  , SUM(CASE WHEN TO_CHAR(hiredate, 'yyyy') = '1980' THEN 1 ELSE NULL END) "1980년"
  , SUM(CASE WHEN TO_CHAR(hiredate, 'yyyy') = '1981' THEN 1 ELSE 0 END) "1981년"
  , SUM(CASE WHEN TO_CHAR(hiredate, 'yyyy') = '1982' THEN 1 END) "1982년"
  , SUM(CASE WHEN TO_CHAR(hiredate, 'yyyy') = '1983' THEN 1 ELSE NULL END) "1983년"
  FROM emp;
Comments