ORACLE [오라클] Grouping 과 Subquery

2020.05.05 21:54

졸리운_곰 조회 수:1159

[오라클] Grouping 과 Subquery

저번 시간에 Aggregation 을 했는데 이것은 집계함수라고도 하며 이 결과는 하나의 row만 남게 된다.

그러므로 Grouping을 해주어야 같이 쓸 수 있다.

 

# Grouping

 

 

이렇게 deptno로 grouping을 해주면 AVG를 쓰는데 문제가 없다.

 

 

 

 SELECT job, avg(sal), max(sal), min(sal) FROM emp GROUP BY job

 

직업별 평균 월급과 최대월급 최소월급을 구하고 싶다.

 

저 뒤에 group by를 써주지 않는다면 이렇게 sql에러가 날 것이다.

 

ORA-00937: 단일 그룹의 그룹 함수가 아닙니다

00937. 00000 -  "not a single-group group function"

 

 

 

select deptno, count(*) from emp group by deptno

 

각 부서에 속해있는 수를 구하고 싶다.

 

 

 

# Stock Clerk 직종의 사원들의 부서별 인원수를 출력하시오.

 

SELECT deptno, COUNT(*) "Number" FROM emp WHERE job = 'CLERK' GROUP BY deptno;

 

 

# 직종별 최고 급여를 급여가 많은 직종부터 출력하시오. 

 

SELECT job, max(sal) FROM emp GROUP BY job ORDER BY max(sal) DESC;

 

 

 

 

 

## Having 절

 

Aggregation 결과에 대해 다시 condition을 검사할 때

 

예를들어 평균 월급이 2000이상인 부서는?

 

select deptno, avg(sal) from emp where avg(sal) > 2000 group by deptno

 

ORA-00934: 그룹 함수는 허가되지 않습니다

00934. 00000 -  "group function is not allowed here"

 

???

 

where절은 aggregation 이전, having절은 aggregation 이후를 필터링한다.

그래서 나온 것이 having절이다. having절은 group by에 참여한 컬럼이나 aggregate 함수만 사용가능하다.

 

# 직종별 최고 급여를 급여가 많은 직종부터 출력하시오. (단, 직원이 2명 이상인 경우만) 

 

SELECT job, max(sal) FROM emp GROUP BY job HAVING count(sal) >= 2 ORDER BY max(sal) DESC; 

 

 

# 부서별 인원수를 부서명과 부서번호와 같이 나타내시오

 

SELECT d.deptno, d.dname, count(e.ename) cnt from emp e, dept d where e.deptno = d.deptno;

 

얼핏 보면 맞는거같다. dept를 d로 emp를 e로 테이블별 alias를 주고 deptno(부서번호), dname(부서명), e.ename으로 카운트세고.

 

ORA-00937: 단일 그룹의 그룹 함수가 아닙니다

00937. 00000 -  "not a single-group group function"

 

?? 또 등장했다.

 

생각해보면 d.deptno는 모든 row의 deptno를 뱉는 것인데 count로 갯수세는 것은 하나의 row를 반환한다고 했다. 그런데 d.deptno는 여러 row여서 서로 아구가 맞지 않는다. group by 로 정리를 해줘야한다. 즉, deptno와 dname을 grouping을 해주는 것이다.

 

SELECT d.deptno, d.dname, count(e.ename) cnt from emp e, dept d where e.deptno = d.deptno group by d.deptno;

 

 

# deptno를 직원들이 없더라도 다 출력하고 싶다.

 

SELECT d.deptno, d.dname, count(e.ename) cnt from emp e, dept d where e.deptno (+) = d.deptno group by d.deptno, d.dname

 

 

# ROLLUP & CUBE 

 

Rollup은 각각의 그룹핑된 것의 소계가 나오고 마지막에 총 소계가 나온다. 무슨 헛소리인가?

 

select deptno, job, sum(sal) from emp group by deptno, job

 

이렇게하면 당연히 밑처럼 나온다.

 

 

근데 rollup을 쓰면

 

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

select deptno, job, sum(sal) from emp group by rollup(deptno, job)

 

각 depno별로 한 번씩 뽑아주고 최종적으로 뽑는다. ㅎㅎ이런 기능이있다니 부서별로 매출이 얼마고 직업별로 얼만지 파악하기에 매우 편하게 쓸 수 있겠다.

 

 

# CUBE

 

아 위에 rollup 진짜 좋은거 같은데 난 부서별로도 보고 싶고 JOB 직업별로도 보고싶어. 그럼 union으로 rollup을 두 번 조져야 된다.

귀찮아서 존재하는 것이 cube이다. 실행결과를 보고 이해해보자.

 

select deptno, job, sum(sal) from emp group by cube(deptno, job)

 

 

roll up 에서 더 확장되었다. 진짜 없는게 없다.

## Subquery

 

서브쿼리란 하나의 SQL 질의문 속에 다른 SQL 질의문이 포함되어 있는 상태이다.

 

SCOTT보다 월급이 많은 사람의 이름은??

 

먼저 해야할 것은 스캇의 월급을 구해야 한다. select sal from emp where ename='SCOTT' 이것을 변수처럼 어디에 넣어서 비교했으면 좋겠다.

 

select ename from emp where sal > ( 위의 쿼리 ) 이런식으로 말이다.

 

하나씩 살펴보자.

 

# Single-Row Subquery

 

Subquery의 결과가 한 ROW인 경우

 

# 평균 급여보다 적게 받는 사원들을 출력하시오

 

SELECT ename, sal FROM emp WHERE sal < (SELECT AVG(sal)FROM emp); 

 

 

 

# Multi-Row query

 

서브쿼리의 결과가 둘 이상의 row일 경우이다.

그렇다면 멀티로우에 대한 연산을 사용해야한다(any,all,in.exist...)

 

SELECT ename, sal, deptno

FROM emp

WHERE ename IN (SELECT MIN(ename)

FROM emp GROUP BY deptno);

 

 

# Correlated Query

 

outer query와 inner query가 서로 연관되어 있음

 

 

 

# 각 부서별로 최고급여를 받는 사원을 출력하시오
 
먼저 부서별 최고급여를 찾아야 한다.
 
(SELECT deptno, max(sal) FROM emp GROUP BY deptno); 
 
이러면 부서명과 최고 급여가 나올 것이다. 이것을 서브쿼리로 치고 메인쿼리에 넣는다.
 
SELECT deptno, empno, ename, sal FROM emp WHERE (deptno,sal) IN (SELECT deptno, max(sal) FROM emp GROUP BY deptno);  => Nested Query

 

이렇게 해도 된다.

테이블 alias는 그냥 테이블 시작알파벳으로 하였다.

 

select  e.deptno, e.empno, e.ename, e.sal from emp e, (select deptno, max(sal) as mxsal from emp group by deptno) m

where e.deptno = m.deptno and e.sal=m.mxsal    => Inline View

 

세 번째 방법

 

SELECT deptno, empno, ename, sal FROM emp e WHERE e.sal = (SELECT max(sal) FROM emp WHERE deptno = e.deptno);    => Correlated Query

 

 

 

# Top - K Query (ORACLE)

 

어떤 조건의 상위 몇 명 찾기. 이러한 쿼리에 쓰인다.

rownum이라고 예약여거 있는데 이것은 질의의 결과에 가상으로 부여되는 Oracle의 Pseudo Column 이다.

 

81년도에 입사한 사람 중 월급이 가장 많은 3명은 누구인가?

 

SELECT rownum, ename, sal FROM (SELECT * FROM emp WHERE hiredate like '81%' ORDER BY sal DESC) WHERE rownum < 4;

 

 

 

 

급여를 많이 받는 순서대로 상위 3명을 출력하시오

 

 SELECT rownum, ename, sal FROM (SELECT * FROM emp ORDER BY sal DESC) WHERE rownum < 4;

 

 

 

 

# Rank 

 

SELECT sal, ename, RANK() OVER (ORDER BY sal DESC) AS rank, DENSE_RANK() OVER (ORDER BY sal DESC) AS dense_rank, ROW_NUMBER() OVER (ORDER BY sal DESC) AS row_number, rownum AS "rownum“ FROM emp;

 

 

 

그냥 rank는 공동 2위는 같이 2라고 표시되고 다음은 해당 공동인원들의 숫자를 건너뛰어 4부터 시작한다. dense rank는 그것을 고려하여 다음은 3으로나온다.



출처: https://pjh3749.tistory.com/165 [JayTech의 기술 블로그]

 

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
공지 오라클 기본 샘플 데이터베이스 졸리운_곰 2014.01.02 86751
공지 [SQL컨셉] 서적 "SQL컨셉"의 샘플 데이타 베이스 SAMPLE DATABASE of ORACLE 가을의 곰을... 2013.02.10 79067
공지 [G_SQL] Sample Database 가을의 곰을... 2012.05.20 95829
724 [Oracle] 오라클 DECODE 함수 사용방법 (if else, 디코드) file 졸리운_곰 2020.05.20 1525
723 [mysql] 운용 application 정보 (proxy, middle ware) 등: awesome-mysql file 졸리운_곰 2020.05.16 26549
722 W3Schools sample Database sql dump file 졸리운_곰 2020.05.16 1919
721 [SQL] join의 on절과 where절 차이 졸리운_곰 2020.05.16 1305
720 JOIN*(3개 테이블) and GROUP BY*(보이지않더라도 key칼럼으로) and ORDER BY 졸리운_곰 2020.05.16 1226
719 다중 테이블에서 데이터 검색 - JOIN file 졸리운_곰 2020.05.16 1601
718 [MySQL] 10장 여러 개의 테이블 이용하기 file 졸리운_곰 2020.05.16 1137
717 [MSSQL] 3개 이상 테이블 조인 file 졸리운_곰 2020.05.16 1604
716 [Greenplum DB] 세계 최초 오픈소스 대용량 데이터 병렬 처리 데이터 분석 플랫폼, Greenplum Database (GPDB) file 졸리운_곰 2020.05.12 2219
715 [MySQL] DB에 중복된 값의 개수를 확인하고 싶다. 졸리운_곰 2020.05.06 1185
714 [ORACLE] ORA-00979: GROUP BY 표현식이 아닙니다 졸리운_곰 2020.05.06 984
713 [Oracle|오라클] NVL, NVL2 함수 사용방법 (null, 공백, 치환) file 졸리운_곰 2020.05.06 1463
712 [Oracle] 오라클 데이터 타입 변환(TO_CHAR, TO_NUMBER, TO_DATE) 사용법 & 예제 졸리운_곰 2020.05.06 1306
711 [oracle] COUNT, SUM, AVG는 NULL을 어떻게 처리할까? file 졸리운_곰 2020.05.06 1089
710 [Oracle] Null값을 치환해주는 (NVL,NVL2) 함수 사용법 & 예제 졸리운_곰 2020.05.06 1156
709 [oracle] [OTN] DATAFILE SIZE를 줄이는 방법 (resize) 졸리운_곰 2020.05.06 1181
708 [SQLD] 서브쿼리와 그룹함수(Group Function) file 졸리운_곰 2020.05.05 716
» [오라클] Grouping 과 Subquery file 졸리운_곰 2020.05.05 1159
706 오라클 Tablespace 생성 및 유저 생성 과 접속 졸리운_곰 2020.05.05 1341
705 [oracle] 오라클 테이블스페이스 생성, 사용자 추가 졸리운_곰 2020.05.05 1323
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED