ch0nny_log

[빅데이터분석] SQL_TIL9 본문

빅데이터 분석(with 아이티윌)/SQL

[빅데이터분석] SQL_TIL9

chonny 2024. 5. 23. 17:09
★점심문제:
사원 테이블에서 입사한 년도(4자리)를 출력하고 입사한 년도별 인원수를 출력하는데1980년은 제외하고 출력하고 입사한 년도별 인원수가 2명 이상인것만 출력하고 입사한 년도별 인원수가 높은것 부터 출력하시오 !  
  select to_char(hiredate, 'RRRR')as 입사년도, count(*) 
        from emp
        where to_char(hiredate, 'RRRR')<>'1980' 
        group by to_char(hiredate, 'RRRR')
        having count(*)>= 2
        order by to_char(hiredate, 'RRRR') desc;​

[TIL 9] _240523

★ 누적치를 구하는 분석 함수의 옵션들 

  • 문법: select ename, sal, sum(sal) over (order by sal asc(desc) rows(range) between unbounded preceding and current row) as 누적치 from emp;
  • 옵션: order by 컬럼 asc/desc , rows/ range
    • rows: 행을 기준으로 누적치를 출력
    • range: 범위를 기준으로 누적치를 출력
    • unbounded preceding: 맨 마지막 행
    • current row: 현재 행
  • rows: 행의 기준으로 누적치를 구하는것
  • range: 범위르 기준으로 누적치를 구하는 것 

Q1. range 를 사용하여 누적 데이터 출력하기

  select ename, sal, 
    sum(sal) over(order by sal asc range 
                                between unbounded preceding 
                                and current row) as 누적치
                from emp;

- 누적 데이터에서 5350 이 2번 나오고 있습니다.

- rows 옵션처럼  행의 값을 기준으로 누적하는게 아니라 값의 범위에 따라 누적하고 있습니다. 

 

 

* 범위(range) 를 기준으로 range 윈도우 기준을 테스트하기 

create table emp2
as
select *
    from emp
    order by deptno  asc;
    
    select * from emp2;

Q2. emp2 테이블의 사원들의 입사일을 부서번호별로 각각 다음과 같이 변경하시오.

update emp2
        set hiredate ='81/01/05'
        where deptno =10;
        
    update emp2
        set hiredate ='81/02/17'
        where deptno =20;
    
       update emp2
        set hiredate ='81/03/21'
        where deptno =30;
        
        commit;

Q3. emp2 테이블에서 이름, 입사일과 월급에 대한 누적치를 출력하시오. 정렬기준이 입사원 사원순으로 정렬하시오.

select ename, hiredate, sal,sum(sal)over (order by hiredate asc rows
                                              between unbounded preceding 
                                              and current  row )as 누적치
                                from emp2;

 

Q4. 위 결과에서 range 로 출력하시오.

  select ename, hiredate, sal,sum(sal)over (order by hiredate asc range
                                              between unbounded preceding 
                                              and current  row )as 누적치
                                from emp2;

문제1. (sqld 기출문제) 아래의 sqld 기출문제를 푸는데 수행되지 않는 sql은 어느 것 인가?
답: 4번. 

 


[TIL 9] _220523

51. RATIO_TO_REPORT

예제51. 데이터 분석 함수로 비율 출력하기(RATIO_TO_REPORT)
Q. 부서번호가 20번인 사원들의 사원번호, 이름, 월급, 월급에 대한 비율을 출력하시오.
select empno, ename, sal, ratio_to_report(sal) over() as 비율,
        sal/sum(sal) over() as 비교비율
        from emp
        where deptno =20;

52. ROLLUP

예제52. 데이터 분석 함수로 집계결과 출력하기(ROLLUP)
Q. 부서번호, 부서번호별 토탈 월급을 출력하시오! (세로)
select deptno, sum(sal)
	from emp
    group by deptno;

 

문제1. 부서번호, 부서번호별 토탈월급을 출력하는데 부서번호별 토탈월급에 전체 합계가 맨 아래 출력되게하시오.
 select deptno, sum(sal)
	from emp
    group by rollup(deptno);
문제2. 직업, 직업별 토탈월급을 출력하는데 맨 아래 전체 토탈월급 출력하시오.
   select job, sum(sal)
        from emp
        group by rollup(job);

 

문제 3. 위 결과에서의 null 을 전체집계로 변환해라.
    select nvl(job,'전체 집계'), sum(sal)
        from emp
        group by rollup(job);
문제4. 통신사, 통신사별 인원수를 출력하시오.
select lower(telecom), count(*)
        from emp19
        where lower(telecom) is not null
        group by lower(telecom);​
문제 5. 위의  결과에서 맨 아래쪽 전체 인원수 출력하시오.
  select nvl(lower(telecom),'전체 인원'), count(*)
        from emp19
        where lower(telecom) is not null
        group by rollup(lower(telecom));
문제 6. 성별, 성별별 인원수를 출력하는데 맨 아럐쪽에 전체 인원수가  출력되게하시오.
 select  nvl(gender,'전체 인원'), count(*)
        from emp19
        where gender is not null
        group by rollup(gender);​

 


53. CUBE

예제 53. 데이터 분석 함수로 집계 결과 출력하기
Q. 부서번호, 부서번호별 토탈월급을  출력하는데 전체 토탈월급을 맨 위에 출력하시오 !
select deptno, sum(sal)
        from emp
        group by cube(deptno);
문제1. 직업, 직업별 인원수를 출력하는데 전체인원수가 맨 위에 출력되게하시오.
   select job, count(*)
        from emp
        group by cube(job);

 

문제2. (rollup 고급기능)  부서번호, 직업,  부서번호별 직업별 토탈월급을 출력하시오.
 select  deptno, job,  sum(sal)
   from   emp
   group  by  deptno, job;
문제 3. ( 올리브영에서 많이 사용하는 SQL) 위의 결과를 다시 출력하는데 다음과 같이 rollup을 같이써서 출력하시오 
 select  deptno, job,  sum(sal)
   from   emp
   group  by  rollup( deptno, job );​

설명: group by rollup(deptno, job) 이라고 하게 되면 3가지의 grouping 된 결과가 출력됩니다.
다음 3가지 입니다.
1. deptno, job
2. deptno
3. 전체

=> rollup 괄호안에 컬럼을 2개를 썼으면 grouping 된 결과가 3개가 나옵니다. rollup 괄호안에 적은 컬럼의 갯수 + 1개 만큼 grouping 된 결과가 출력되는 것.
문제5. 위의 결과를 다음과 같이 추출하시오.

  select deptno, nvl(job,'부서 토탈'),  sum(sal)
   from   emp
   group  by  rollup( deptno, job );

 

 

★ 문제 6. ( 진짜 올리브영에서 많이 사용하는 SQL) 위의 결과를 다시 출력하는데 다음과 같이 출력하시오 
SELECT deptno, DECODE(deptno, NULL, '전체토탈:', nvl(job, '부서토탈:')), sum(sal)
 FROM emp
 GROUP BY ROLLUP(deptno, job)
 ORDER BY deptno;​
문제7. 부서번호, 부서번호별 토탈월급을 출력하는데 맨아래쪽에 전체 토탈월급을 출력하시오.
select deptno, sum(sal)
    from emp
    group by rollup(deptno);
문제8. emp19에서 성별, 통신사, 성별별 통신사별 평균 나이 출력하시오.
 select gender, lower(telecom), round( avg(age))
        from emp19
        where gender is not null
        group by gender, lower(telecom)
        order by gender asc;
문제9. 위의 결과에서 성별별 평균 나이도 같이 출력되게하고 전체 평균도 맨 아래에 출력되게하시오.
 select gender, lower(telecom), round( avg(age))
        from emp19
        where gender is not null
        group by rollup(gender, lower(telecom))
        order by gender asc;


※ grouping 된 결과 
 1. gender, lower(telecom)
 2. gender
 3. 전체

 

문제 10. 위의 결과에서 평균나이-> 인원수로 출력하시오
select gender, lower(telecom), count(*)
        from emp19
        where gender is not null
        group by rollup(gender, lower(telecom))
        order by gender asc;

 


53. GROUPING SET

예제 54. 데이터 분석 함수 집계 결과 출력하기(GROUPING SET)
 = ROLLUP/CUBE 보다 결과를 예상하기 쉬워서 자주 사용하는 함수

Q1. 부서번호, 부서번호 별 토탈월급을 출력하는데 맨아래에 전체 토탈월급을 출력하시오.
 1)rollup       
    select deptno, sum(sal)
        from emp
        group by rollup(deptno);
        
 2)grouping sets
    select deptno, sum(sal)
        from emp
        group by grouping sets(deptno,());​
        
        
     # grouping sets (컬럼 , ())
     = () 가 전체를 나타냄
문제1. 직업과 직업별 토탈월급을 출력하는데 맨 아래 전체 토탈월급도 출력하시오
 select job, sum(sal)
            from emp
            group by grouping sets(job,());
문제2. 위의 결과를 cube 작성과 같이 전체 토탈로 나오게하시오.
select job, sum(sal)
            from emp
            group by grouping sets(job,())
            order by job nulls first;

 

문제3. 우리반 테이블에서 통신사, 통신사별 인원수를 출력하는데 전체 인원수가 맨아래가 되게 출력하시오,( grouping sets)
select nvl(lower(telecom),'전체건수'), count(*)
            from emp19
            where lower(telecom) is not null
            group by grouping sets (lower(telecom),())
            ;
문제4. 아래의 rollup 결과를 grouping sets로구현하시오.
    select gender, lower(telecom), count(*)
        from emp19
        where lower(telecom)is not null
        group by rollup( gender, lower(telecom));

select gender, lower(telecom),  count(*)
    from   emp19
    where  gender is  not  null
    group  by  grouping  sets( (gender, lower(telecom)), (gender),()  );
문제5. 아래의 rollup 결과를 grouping sets 로 수행하시오.
select deptno, job, sum(sal)
        from emp
        group by rollup(deptno, job);​

select deptno, job, sum(sal)
        from emp
        group by grouping  sets((deptno, job),(deptno),())
        order by deptno ;
문제5. (올리브영 요청 sql) 다음과  같이 결과를 출력하시오.

 select empno, ename, sum(sal)
            from emp
            where empno is not null
            group by grouping sets((empno,ename ),());

 

문제6. 이름, 커미션(null->0) 출력하시오,
select ename, nvl(comm,0)
                from emp;
문제 7. 위의 결과에서 comm이 null인사원들은 no comm으로 출력되게하시오,
 select ename,nvl( to_char(comm), 'no comm')
                from emp;
문제8.(복습문제)  부서번호, 부서번호별 토탈월급을 출력하는데 맨 아래쪽에 전체 토탈월급을 출력하시오 
 select deptno, sum(sal)
                    from emp
                    group by rollup(deptno);​

 

문제 9. 위의 결과에서  전체 토탈이라는 글씨가 아래에 출력되게하시오.
 select  nvl(to_char(deptno),'전체토탈:'),  sum(sal)
   from  emp
   group   by   rollup(deptno);

 

 


55. ROW_NUMBER

예제55. 데이터 분석 함수로 출력결과 넘버링하기(ROW_NUMBER)
: ROW_NUMBER 함수는 출력결과에 번호를 넘버링하는 함수

Q1. 직업이 SALESMAN 인 사원들의 이름, 월급, 직업을 출력하시오.
Select ename, sal, job
	from emp
    where job = 'SALESMAN';​

Q2. 위에서 출력되는 결과 앞에 번호를 순서대로 부여해서 출력하시오.

Select rownum,ename, sal, job
	from emp
    where job = 'SALESMAN';
※ rownum은 출력되는 결과에 숫자를 numbering 하는 shadow컬럼

 

문제1. 부서번호가 10,20 사원들의 이름, 월급과 부서번호를 출력하는데 출력할때 앞에 번호흐 넘버링해서 출력하시오
 
    select rownum, ename, sal, deptno
        from emp
        where deptno in (10,20)
;
문제2. 사원 테이블에서 모든 컬럼의 데이터를 출력하는데 위에 3줄의 행만 출력하시오 !

select * from emp
                    where rownum <=3;​

 

문제 3. 직업이 salesman 사람들의 이름, 월금, 직업을 출력하는데 앞 rownum 을 이용하여 숫자를 넘버링하세요
Select rownum,ename, sal, job
	from emp
    where job = 'SALESMAN';
문제 4. 위 결과에서 월급이 높은 사원부터 출력하시오
Select rownum,ename, sal, job
	from emp
    where job = 'SALESMAN'
    order by sal desc;
설명: 출력되는 번호가 1,2,3 순이 아니게됨 -> order by가 맨 나중에 수행되었기 때

 

문제 5. 위 결과에서 rownum 순서가 1,2,3 이 되도록하시오.
Select rownum,ename, sal, job
	from (select ename, sal, job from emp
    where job = 'SALESMAN'
    order by sal desc
    );
설명: from 절에 subquery 를 사용 하여 rownum 의 순서가 제대로 되게끔 함
- 괄호안에 있는 쿼리문의 결과가 하나의 집합이 되면서 마치 테이블처럼 사용되게 함 (in line view)
** row_number() 을 이용하면 서브쿼리 이용안해도됨
select row_number() over (order by sal desc) 번호,
                    ename, sal, job from emp
                    where job = 'SALESMAN';​
문제 6. emp19 에서 통신사가 sk인 학생들의 이름,나이, 통신사를 출력하는데 나이가 높은 학생부터 출력하시오. 그리고 맨앞 숫자를 순서대로 넘버링하시오.
  select row_number() over (order by age desc) 번호, ename, age, lower(telecom)
                from emp19
                where age is not null
                order by age desc;
문제 7. 통신사가 'sk' 학생중에서 나이가 2번째로 많은 학생의 이름나이 통신사 출력하시오
 select 번호, ename, age, telecom
  from   (  
     select  row_number() over (order  by  age  desc) 번호, ename, age, telecom
        from  emp19
        where  lower(telecom)='sk'   
           )
  where  번호 = 2;
문제 8. 월급을 5번째로 많이 받는 사원의 이름과 월급을 출력하시오
select 번호, ename, sal
    from(
    select row_number() over(order by sal desc) 번호, ename, sal
    from emp
    )
    where 번호=5;

 


56. ROWNUM

예제 56. 출력되는 행 제한하기 1 (ROWNUM)
ROWNUM() 함수와 ROWNUM의 차이점?
1. row_number() 함수는 정렬된 결과에 번호를 넘버링하고 싶을 때 사용
select row_number() over ( order by sal desc ) 번호, ename, sal 
from emp 
where job='SALESMAN';​

- 주로 큰테이블의 일부 데이터를 보고싶을 때 사용


 2. rownum 은 그냥 쿼리문의 출력 결과에 번호를 넘버링하고 싶을 때 사용
select rownum as 번호, ename, sal 
from emp 
where job='SALESMAN';​
문제1. 사원 테이블에서 사원이름, 월급을 출력하는데 ROWNUM이 1번인 것을 출력하시오,
  select rownum, ename, sal
        from emp
        where rownum = 1;

2번만 나오게 못함

select rownum, ename, sal
        from emp
        where rownum <=2;

 


57. Simple Top-n queries

예제 57. 출력되는 행 제한하기 2 (Simple Top-n queries)
- 정렬된 결과에서 상위 몇개의 데이터를 가져오는 방법
order by 컬럼명 asc/desc fetch first 숫자 rows only

Q 사원테이블에서 이름과 월급을 출력하는데 월급이 높은 사원부터 출력하고 출력된 결과에서 2번째 행까지 출력하시오.

select ename, sal
            from emp
            order by sal desc fetch first 2 rows only;​

 


56. EQUI JOIN

예제 58. 여러테이블의 데이터를 조인해서 출력하기 1. (EQUI JOIN)
여러 테이블의 결과를 하나의 결과로 출력하려면 조인문법을 알아야 됨
- JOIN이란? 
: 여러개의 테이블의 컬럼들의 결과를 하나로 모아서 출력해주는 SQL 문법
ex) king사원은 어느 부서에서 근무하는가 ? emp 테이블 가지고만은 알 수 없음
select * from dept;​

테이블명 : dept <--- 부서에 대한 정보를 담고 있는 테이블
- deptno :부서번호
- dname : 부서명
- loc : 부서위치
문제1. emp와 dept를 조인해서 이름과 부서(loc)를 출력하시오.
select ename, loc
    from emp, dept
    where emp.deptno =dept.deptno;
문제2. (삼성 디스플레이) 아래 그림처럼 출력하시오.

  select nvl(job,'토탈값') as job , sum(decode(deptno, '10',sal)) as "10" ,
            sum(decode(deptno, '20',sal)) as "20" ,
            sum(decode(deptno, '30',sal)) as "30"  , sum(sal) as 토탈값      
    from emp
    group by rollup(job)
    order by 1 asc;