SELECT dept, SUM(sal) FROM emp; -- 에러
-- 일반컬럼인 dept와 SUM() 집게함수는 함께 사용 불가
-- score
90
null
90
AVG(score) -- 90, null은 무시 (없는 자료)
AVG(NVL(score, 0) -- 60
COUNT(score) -- 2
COUNT(*) -- 3 모든 행수를 구하는 것
SELECT COUNT(empNO) FROM emp;
SELECT COUNT(empNO) FROM emp;
SELECT COUNT(empNO) FROM emp WHERE city = '미국';
SELECT AVG(empNO) FROM emp;
SELECT AVG(empNO) FROM emp WHERE city = '미국'; -- null
SELECT COUNT(*) FROM emp; -- 전체 행수
SELECT COUNT(empNo) FROM emp; -- 컬럼에 null이 아닌 데이터의 개수
-- * 나 PRIMARY KEY 컬럼, NOT NULL 컬럼을 이용하여 COUNT 하면 전체 행수
SELECT COUNT(tel) FROM emp; -- null은 카운트 하지 않는다.
-- 서울 사람 인원수
SELECT COUNT(*)
FROM emp
WHERE city = '서울';
-- 부서의 수
SELECT COUNT(DISTINCT dept)
FROM emp;
-- 서울 사람이면서 남자 인원수
SELECT COUNT(*)
FROM emp
WHERE city = '서울' AND MOD(SUBSTR(rrn,8,1), 2) = 1;
-- 전체인원수, 남자인원수, 여자인원수(1줄로 출력)
SELECT COUNT(*) 전체, COUNT(DECODE(MOD(SUBSTR(rrn, 8, 1), 2),1 ,1)) 남자,
COUNT(DECODE(MOD(SUBSTR(rrn, 8, 1), 2),0, 1)) 여자
FROM emp;
-- 전체인원수, 남자인원수, 여자인원수
-- 구분 인원
SELECT '전체' 구분, COUNT(*) 인원
FROM EMP
UNION ALL
SELECT '남자', COUNT(*)
FROM emp
WHERE MOD(SUBSTR(rrn, 8 ,1), 2) = 1
UNION ALL
SELECT '여자', COUNT(*)
FROM emp
WHERE MOD(SUBSTR(rrn, 8, 1), 2) = 0;
SELECT MIN(sal), MAX(sal)
FROM emp;
-- 최소 나이와 최대 나이를 구해라
SELECT MIN(TO_DATE(SUBSTR(rrn, 1, 6), 'RRMMDD')) 고,
MAX(TO_DATE(SUBSTR(rrn, 1, 6), 'RRMMDD')) 저
FROM emp;
SELECT AVG(sal), SUM(sal)
FROM emp;
-- sal 합, 남자 sal 합, 여자 sal 합
SELECT '전체' 구분, SUM(sal) 합
FROM EMP
UNION ALL
SELECT '남자', SUM(sal) FROM emp WHERE MOD(SUBSTR(rrn, 8 ,1), 2) = 1
UNION ALL
SELECT '여자', SUM(sal) FROM emp WHERE MOD(SUBSTR(rrn, 8, 1), 2) = 0;
-- sal 전체평균 남자 sal 평균, 여자 sal 평균 한줄로
SELECT TRUNC(AVG(sal)) 전체,
TRUNC(AVG(DECODE(MOD(SUBSTR(rrn, 8, 1), 2), 1, sal))) 남자,
TRUNC(AVG(DECODE(MOD(SUBSTR(rrn, 8, 1),2),0, sal))) 여자
FROM emp;
-- 월별 입사 인원수
-- 전체 1월 2월 ... 12월
SELECT COUNT(*) 전체,
COUNT(DECODE(TO_CHAR(hireDate, 'MM'), '01', '1')) "1월" ,
COUNT(DECODE(TO_CHAR(hireDate, 'MM'), '02', '2')) "2월"
FROM emp;
-- 급여(sal)가 가장 높은 사람의 이름, 급여
SELECT name, sal
FROM emp
WHERE sal = MAX(sal); -- 에러 WHERE 절에는 집계함수를 사용할 수 없다.
SELECT name, sal
FROM emp
WHERE sal =(SELECT MAX(sal) FROM emp);
-- SELECE 안에 또 SELECT 넣는 걸 서브쿼리라 한다.
-- 평균 급여(sal) 보다 적게 받는 사람의 이름, 급여
SELECT name, sal
FROM emp
WHERE sal < (SELECT AVG(sal) FROM emp);
SELECT name, (SELECT city FROM emp WHERE city = '서울')
FROM emp; -- 에러 서브 쿼리가 여러줄
SELECT name, (SELECT AVG(sal) FROM emp)
FROM emp;
SELECT name, sal - (SELECT AVG(sal) FROM emp)
FROM emp;
SELECT name, sal
FROM emp
WHERE sal >= (SELECT sal FROM emp WHERE city = '인천');
-- 에러 , 인천 sal가 하나가 아니다. 누구랑 비교하는지 모르기 때문에 사용불가
SELECT name, sal
FROM emp
WHERE sal IN (SELECT sal FROM emp WHERE city = '인천');
-- IN은 하나만 만족하면 되기때문에 사용 가능
-- 서울 사람이 아닌 사람들 중에 평균(sal) 보다 많이 받는 사람(name, sal, city)
SELECT name, sal, city
FROM emp
WHERE city <> '서울' AND sal > (SELECT AVG(sal) FROM emp WHERE city = '서울');
-- name, sal, 최대급여와의차이
SELECT name, sal, (SELECT MAX(sal) FROM emp) - sal 차이
FROM emp ;
-- 여자들 sal를 가장 많이 받는 사람(name, rrn, sal)
SELECT name, rrn, sal
FROM emp
WHERE MOD(SUBSTR(rrn, 8,1),2) = 0 AND
sal = (SELECT MAX(sal) FROM emp WHERE MOD(SUBSTR(rrn, 8, 1),2) = 0);
-- sal + bonus가 가장 많은 사람(name, sal, bonus, sal + bonus)
SELECT name, sal, bonus, sal + bonus pay
FROM emp
WHERE sal + bonus = (SELECT MAX(sal + bonus) FROM emp);
-- 부서별 인원수가 가장 많은 부서명과 인원수
SELECT MAX( COUNT(*))
FROM emp
GROUP BY dept
HAVING COUNT(*) = (SELECT MAX( COUNT(*)) FROM emp GROUP BY dept);
-- 입사 인원수가 가장 많은 년도 및 인원수 출력
SELECT TO_CHAR(hireDate, 'YYYY'), COUNT(*)
FROM emp
GROUP BY TO_CHAR(hireDate, 'YYYY');
HAVING은 SELECT에서 사용가능한건만 HAVING에 올 수 있다.
-- 입사 인원수가 가장 많은 년도 및 인원수 출력
SELECT TO_CHAR(hireDate, 'YYYY'), COUNT(*)
FROM emp
GROUP BY TO_CHAR(hireDate, 'YYYY');
-- 입사년도별 인원의 최대값
SELECT MAX(COUNT(*))
FROM emp
GROUP BY TO_CHAR(hireDate, 'YYYY')
-- GROUP BY EXTRACT(YEAR FROM hireDate);
HAVING COUNT(*) =
(SELECT TO_CHAR(hireDate, 'YYYY'), COUNT(*)
FROM emp
GROUP BY TO_CHAR(hireDate, 'YYYY'));
-- TO_CHAR 날짜, 숫자를 문자 데이터로 바꾸는 것
-- 단일행에서만 사용이 가능하다.
-- 집계함수는 일반 컬럼과 사용할 수 없다.
-- 나온 결과에 값이 들어가면 HAVING이 들어간다.
-- 다른 방법
WITH tb AS(
SELECT TO_CHAR(hireDate, 'YYYY') 년도, COUNT(*) 인원수
FROM emp
GROUP BY TO_CHAR(hireDate, 'YYYY')
) -- 테이블
SELECT 년도, 인원수
FROM tb
WHERE 인원수 = ( SELECT MAX(인원수) FROM tb );
-- 생일이 동일한 사람이 2명 이상인 경우
SELECT name, TO_DATE(SUBSTR(rrn,1,6), 'RRMMDD') birth
FROM emp
ORDER BY TO_CHAR(birth, 'MMDD');
-- TO_DATE는 숫자로 된 형식을 날짜로 바꾸는 것이고
-- TO_CHAR는 날짜나 숫자로 된것을 문자로 바꾸는 것
SELECT SUBSTR(rrn, 3, 4), COUNT(*)
FROM emp
GROUP BY SUBSTR(rrn, 3, 4);
SELECT SUBSTR(rrn, 3, 4), COUNT(*)
FROM emp
GROUP BY SUBSTR(rrn, 3, 4)
HAVING COUNT(*) >= 2;
SELECT name, TO_DATE(SUBSTR(rrn, 1, 6), 'RRMMDD') birth
FROM emp
WHERE SUBSTR(rrn, 3, 4) IN (
SELECT SUBSTR(rrn, 3, 4)
FROM emp
GROUP BY SUBSTR(rrn, 3, 4)
HAVING COUNT(*) >= 2
)
ORDER BY TO_CHAR(birth, 'MMDD');
-- 여러개 있는건 IN으로 비교하자
GROUP BY절에는 컬럼만 SELECT에서 사용이 가능
ROLLUP 집계 예
| 표현식 | 집계 |
|---|---|
| GROUP BY ROLLUP(expr1, epxr2) | expt1 + expr2 |
| expr1 | |
| 전체 | |
| GORUP BY expr1, ROLLUP(expr2, expr3) | expr1 + (expr2 + epxr3) |
| expr1 + (expr2) | |
| expr1 | |
| GROUP BY ROLLUP(expr1), epxr2 | expr2 + expr1 |
| expr2 |
ROLLUP(expr2, epx3)을 하나의 컬럼으로 - 3레벨
SELECT dept, pos, SUM(sal)
FROM emp
GROUP BY ROLLUP(dept,pos)
ORDER BY dept, pos;
-- ROLLUP에 표현식이 2개 -> 3레벨
-- 부서 직위
-- 부서 합계
-- 전체 합계
-- DEPT별 POS의 SAL 소계, DEPT별 소계 출력하여 마지막에 총계는 출력하지 않는다.
SELECT dept, pos, SUM(sal)
FROM emp
GROUP BY dept, ROLLUP(pos) -- pos의 대한 합계, 전체 합계
ORDER BY dept, pos;
-- 부서별 인원수 및 마지막에 전체 인원수 출력
-- dept 전체인원수
SELECT dept, COUNT(*)
FROM emp
GROUP BY ROLLUP(dept); -- 부서 합계 , 전체 합계 총 2레벨이 나옴
-- dept 별 남자와 여자 인원수 및 dept 인원수, 전체 인원수
-- dept 성별 인원
-- 개발부 여자 x
-- 개발부 남자 x
SELECT dept, DECODE(MOD(SUBSTR(rrn, 8,1),2),1, '남자', '여자') 성별, COUNT(*)
FROM emp
GROUP BY dept, MOD(SUBSTR(rrn, 8,1),2)
ORDER BY dept;
SELECT dept, DECODE(MOD(SUBSTR(rrn, 8,1),2),1, '남자', 0, '여자') 성별, COUNT(*)
FROM emp
GROUP BY ROLLUP( dept, MOD(SUBSTR(rrn, 8,1),2))
ORDER BY dept;

| 표현식 | 집계 |
|---|---|
| GROUP BY CUBE(expr1, epxr2) | expr1 + expr2 |
| expr1 | |
| expr2 | |
| 전체 | |
| GROUP BY expr1, CUBE(expr2, expr3) | expr1 + (expr2 + expr3) |
| expr1 + (expr2) | |
| expr1 + (expr3) | |
| expr1 |
-- dept별 pos의 sal 소계, dept별 소계, pos별 소계, 마지막에 총계 출력
SELECT dept, pos, SUM(sal)
FROM emp
GROUP BY CUBE(dept, pos)
ORDER BY dept, pos;SELECT dept, pos, GROUPING(dept), GROUPING(pos), TRUNC(AVG(sal))
FROM emp
GROUP BY ROLLUP(dept, pos);
SELECT dept, TRUNC(AVG(sal))
FROM emp
GROUP BY ROLLUP(dept, pos)
HAVING GROUPING(pos) = 1;SELECT dept, empNo, name, GROUP_ID(),SUM(sal)
FROM emp
GROUP BY ROLLUP (dept, (empNo, name))
ORDER BY dept;
SELECT dept, empNo, name, GROUP_ID(),SUM(sal)
FROM emp
GROUP BY dept, ROLLUP (dept, (empNo, name))
ORDER BY dept, GROUP_ID(), empNo;
SELECT dept, empNo,GROUP_ID(),
DECODE(GROUP_ID() , 0, NVL(NAME, '합계'), '평균') name,
DECODE(GROUP_ID(), 0, SUM(sal), ROUND(AVG(sal))) sal
FROM emp
GROUP BY dept, ROLLUP (dept, (empNo, name))
ORDER BY dept, GROUP_ID(), empNo;