728x90
반응형

Temp를 이용한 문제를 풀어보자

Temp에 있는 직원들을 부서별 직급별로 SALARY 을 보려한다 이때 부서별로 직급들이 동일행에 나오도록

보여주고 부서별 전체급여 그리고 PER컬럼의 전체 부서 급여합계 비율을 구하여라

 

SELECT CASE WHEN DEPTNO IS NOT NULL THEN DEPTNO ELSE '합계' END DEPTNO

, SUM(A.부장) 부장, SUM(A.차장) 차장, SUM(A.과장) 과장

, SUM(A.대리) 대리, SUM(A.사원) 사원, SUM(A.수습) 수습, SUM(A.PER) 전체급여비율

, SUM(A.SAL) 부서별급여합계

FROM (SELECT DEPT_CODE DEPTNO, SALARY SAL

                               , SUM(CASE WHEN LEV = '부장' THEN SALARY ELSE 0 END) 부장

                               , SUM(CASE WHEN LEV = '차장' THEN SALARY ELSE 0 END) 차장

                               , SUM(CASE WHEN LEV = '과장' THEN SALARY ELSE 0 END) 과장

                               , SUM(CASE WHEN LEV = '대리' THEN SALARY ELSE 0 END) 대리

                               , SUM(CASE WHEN LEV = '사원' THEN SALARY ELSE 0 END) 사원

                               , SUM(CASE WHEN LEV = '수습' THEN SALARY ELSE 0 END) 수습

                               , ROUND(RATIO_TO_REPORT(SALARY) OVER (),2) * 100 AS PER

                               , SUM(SALARY)

             FROM TEMP

             GROUP BY DEPT_CODE, SALARY, LEV

              ) A

GROUP BY ROLLUP(DEPTNO)

ORDER BY DEPTNO

 

-->  컬럼 합계를 하기위해서는 ROLLUP()필요하다

그리고 select 문에 DEPTNO별로 소계를 한다면 DEPTNO가 NULL이 되어서 CASE문에 합계라는 문자를 줄 수 있다  

밑의 2개의 구문으로 컬럼의 합계를 표현할 수 있다

 

SELECT CASE WHEN DEPTNO IS NOT NULL THEN DEPTNO ELSE '합계' END DEPTNO

GROUP BY ROLLUP(DEPTNO)

 

 

TEST02 테이블의 자료를 이용해 최대 CRATE를 가지는 일자의 AMT와 최소 CREATE를 가지는 일자의 AMT를 읽어오는 문장을 출력하시오

 

SELECT distinct LAST_VALUE(AMT) OVER ( ORDER BY CRATE

                                                                                        ROWS BETWEEN UNBOUNDED PRECEDING

                                                                                        AND UNBOUNDED FOLLOWING) MAX_VAL,

FIRST_VALUE(AMT) OVER( ORDER BY CRATE

                                                      ROWS BETWEEN UNBOUNDED PRECEDING

                                                      AND UNBOUNDED FOLLOWING) MIN_VAL

FROM TEST02

728x90
반응형
728x90
반응형

CASE, GROUP BY 활용

 

'HP'라는 제품은 너무 많은 등급을 가지고 있어 제품별로 분석하기를 원하고,

'LD'라는 제품은 등급의 수가 적고 중요하므로 등급별로 분석하기를 원하며,

'PP'라는 제품은 다양한 등급을 가지고 있으나 'P530C'라는 등급은 전략적으로 관리하고자 하여 등급별로 분석하고,

나머지는 기타로 모아주기를 원한다고 생각하자

 

이런 경우에는 CASE와 GROUP BY를 활용하여 풀어보자

 

SELECT

   CASE WHEN 제품 = ‘HP’ THEN 제품

   WHEN 제품 = ‘LD’ THEN 등급 ,

   WHEN 등급 = ‘P530C’ THEN 등급

   ELSE ’기타‘

   END

FROM 매출테이블

WHERE 매출일자 LIKE ’9808%’

GROUP BY CASE WHEN 제품 = ‘HP’ THEN 제품

                                  WHEN 제품 = ‘LD’ THEN 등급 ,

                                  WHEN 등급 = ‘P530C’ THEN 등급

ELSE '기타'

END

 

 

SALE_HIST 테이블을 참조하여 ‘PENCIL’ 총 판매금액과 01번 사업장의 총판매금액과

ERASER를 판매하고 있는 사업장의 총판매 금액을 출력하고 그 나머지를 기타로 묶어 총 판매금액을 출력하시오

SELECT

   CASE WHEN SALE_ITEM = 'PENCIL' THEN SALE_ITEM

   WHEN SALE_ITEM = 'ERASER' THEN SALE_SITE

   WHEN SALE_SITE = 01 THEN SALE_SITE

   ELSE '기타'

   END AS 특별관리항목,

   SUM(SALE_AMT) AS 총판매금액

FROM SALE_HIST

GROUP BY CASE WHEN SALE_ITEM = 'PENCIL' THEN SALE_ITEM

                                  WHEN SALE_ITEM = 'ERASER' THEN SALE_SITE

                                  WHEN SALE_SITE = 01 THEN SALE_SITE

ELSE '기타'

END

 

 

TEST100 테이블을 참조하여 C2에 해당하는 값의 비율을 구하여라

SELECT C1, C2

,ROUND(RATIO_TO_REPORT(C2) OVER(),2) * 100 AS PER

FROM TEST100

 

 

TEST35 테이블을 참조하여 KEY1은 부서라고 생각하고 KEY2의 A는 판매액 B는 매입액이라고 할 때

부서별 판매액과 매입액의 차에대한 값(수익)을 구하고 차액의 비율을 구하시오

SELECT

CASE WHEN KEY1 IS NOT NULL THEN KEY1 ELSE '합계' END AS KEY1

   , SUM(CASE WHEN KEY2 = 'A' THEN AMT ELSE 0 END) AS 판매액

   , SUM(CASE WHEN KEY2 = 'B' THEN AMT ELSE 0 END) AS 매입액

   , SUM(CASE WHEN KEY2 = 'A' THEN AMT ELSE - AMT END) AS 수익

   , ROUND(SUM(CASE WHEN KEY2='A' THEN AMT ELSE -AMT END)/ SUM(CASE WHEN KEY2='A' THEN AMT END)*100 )AS PER

FROM (SELECT KEY1, KEY2, SUM(AMT) AMT

               FROM TEST35

               GROUP BY ROLLUP(KEY1), KEY2

)

GROUP BY CASE WHEN KEY1 IS NOT NULL THEN KEY1 ELSE '합계' END

ORDER BY KEY1

728x90
반응형
728x90
반응형

8. 부서번호가 50인 사원들 중 이 부서의 평균 급여액보다 낮은 월급을 받는 사원 명단을 추출하시오

SELECT a.employee_id, a.last_name, a.salary

FROM ( SELECT employee_id, manager_id, salary, last_name

FROM employees WHERE department_id = 50 ) a,

 

(SELECT AVG (salary) avg_salary

FROM employees WHERE department_id = 50 ) b

WHERE a.salary < b.avg_salary

 

 

10. 9번의 출력문을 다시 with을 사용하여 다시 작성하시오

WITH a AS  (SELECT employee_id, manager_id, salary, last_name

                         FROM employees

                         WHERE department id = 50 ),

 

             b AS (SELECT AVG(salary) avg_salary

                         FROM employees

                         WHERE department id = 50)

SELECT a.employee id, a.last_name, a.salary

FROM a, b

WHERE a. salary < b.avg_salary

 

 

11. 전체 부서별 평균 급여액보다 부서별 급여 합계액이 큰 부서의 명단을 추출해 보자 단 서브쿼리

SELECT d.d_dep, d.SUM_sal

FROM

(SELECT a.department_name d_dep, ROUND(SUM(b.salary)) SUM_sal

FROM departments a

, employees b

WHERE a.department_id = b.department_id

GROUP BY a.department_name

) d,

(SELECT ROUND(SUM(sum(b.salary)) / COUNT(*)) AVG_sal

FROM departments a

, employees b

WHERE a.department_id = b.department_id

GROUP BY a.department_name

) c

WHERE d.SUM_sal > c.AVG_sal;

 

 

12 위의 방법을 다시 WITH를 이용하여 다시 작성하시오

WITH dept_costs AS (SELECT department_name, SUM(salary) dept_total

                                            FROM employees e, departments d

                                            WHERE e.department_id = d.department_id

                                            GROUP BY department_name ),

            avg_cost AS (SELECT SUM(dept_total) /COUNT (*) avg

                                       FROM dept_costs)

 

SELECT dept_costs.*

FROM dept_costs, avg_cost

WHERE dept_costs.dept_total > avg_cost.avg

 

 

13. WITH은 SELECT 절과 같이 쓰여 아주 유용한 기능을 제공한다.

10장에서 계층형 쿼리에 대해 학습했는데, 계층형 쿼리를 이용하여 EMPLOYEES 테이블에 있는 사원들을 계층적으로 조회하였다

 

SELECT LEVEL, LPAD(' ', 4* (LEVEL -1)) || first_name || ' ' || last_name "성명"

FROM employees

START WITH MANAGER_ID IS NULL

CONNECT BY manager_id = PRIOR employee_id;

 

계층형 정보를 꼭 CONNECT BY 절을 사용해서만 구현할 수 있는 것은 아니다. WITH 구문을 사용하여 위의 결과와 동일한 데이터를 추출하는 쿼리를 작성해 보자.

 

(힌트: 실제 EMPLOYEES 테이블의 사원 계층은 총 4레벨까지 존재하므로, 레벨 별로 인라인 뷰를 4개 생성해서 WITH을 사용해 생성한 인라인 뷰에서 다른 인라인 뷰를 참조하는 형태로 작성하자. 문제는 난 이도가 꽤 높다. 따라서 이 문제를 풀 정도먼 WITH 구문을 완전히 이해했다고 볼 수 있다 )

 

 

15. 0RDERS 테이블을 참조하여 연도별로 주문건수와 총 주문금액을 구하는 쿼리를 작성해 보자.

 

 

 

16. 1번 쿼리를 기준으로 해서 다음과 같은 형태의 정보를 조회하는 쿼리를 작성해 보자.

기준연도 주문건수 주문총액 이전연도_주문총액 이후연도_주문총액

xxxx 00 0000 0000000 000000

SELECT order_date, order_status, order_total,

SUM(order_total) OVER ( ORDER BY order_date

                                                    RANGE interval '1' year preceding ) AS 이전연도_총합계,

SUM(order_total) OVER ( ORDER BY order_date

                                                    RANGE BETWEEN CURRENT row AND interval '1' year following) AS 이후년도_총합계

FROM ORDERS

 

단 이전연도와 이후연도는 기준연도에서 1년을 더하거나 뺀 연도가 아니라

실제 집계된 데이터가 존재하는 연도를 말한다.

 

 

17. 1999년도 전체 영업실적 중 각 개인별 실적 비율을 구해보자

전체 실적금액으로 각 개인별 실적금액을 니누면 된다 윈도우 함수를 중 분석함수를 사용해서 풀어보자

SELECT emp.last_name 이름, SUM (ord.ORDER_total) 개인별실적,

ROUND(SUM(ord.order_total) / SUM(SUM(ord.order_total)) OVER( PARTITION BY TO_CHAR(ord.order_date, 'YYYY' ) ) ,2) 개인별비율

FROM orders ord, employees emp

WHERE TO_CHAR(ord.ORDER_date, 'YYYY') = '1999'

AND ord. sales_rep_id = emp. employee_id

GROUP BY emp.last_name, TO_CHAR(ord.order_date, 'YYYY')

ORDER BY emp.last_name;

 

 

18. 위의 결과물과 같은 출력값을 가질 수 있게 RATIO_TO_REPORT 함수를 써서 출력하시오

SELECT emp.last_name 이름, SUM(ord.order_total) 개인별실적,

ROUND (RATIO_TO_REPORT(SUM(ord.order_total)) OVER (PARTITION BY TO_chAR(ord.order_date, 'YYYY' )),2) RATIO

FROM orders ord, employees emp

WHERE TO_CHAR(ORD.ORDER_DATE, 'YYYY') = '1999'

AND ord.sales_rep_id = emp.employee_id

GROUP BY emp.last_NAME, TO_CHAR(ord.ORDER_DATE, 'YYYY')

ORDER BY emp.last_name;

728x90
반응형
728x90
반응형

1. TEST12 테이블을 참고하여 BOOK_TYPE별 가격 합계액을 구하시오 (BOOK_TYPE, PRICE만 출력)

SELECT BOOK_TYPE, SUM(PRICE)

FROM TEST12

GROUP BY BOOK_TYPE

 

 

2. 1번의 답을 참고하며, 이번에는 BOOK_TYPE의 소계를 구하시오 (BOOK_TYPE, PRICE만 출력)

SELECT BOOK_TYPE, SUM(PRICE)

FROM TEST12

GROUP BY BOOK_TYPE, ROLLUP(BOOK_NAME)

 

 

3. 1번의 답을 찹고하며, 이번에는 BOOK_TYPE별 가격 합계액을 구하시오

(BOOK_TYPE, PRESS, BOOK_NAME의 3개 컬럼의 정보를 출력하시오)

SELECT PRESS, BOOK_TYPE, SUM(PRICE)

FROM TEST12

GROUP BY PRESS, ROLLUP(BOOK_TYPE)

 

 

4. EMP, DEPT 테이블을 참고하여 부서별로 총 인원수와 급여 합계를 구하시오 (DNAME 출력하시오)

SELECT b.dname, SUM(a.sal) sal, COUNT(a.empno) emp_count

FROM emp a, dept b

WHERE a.deptno = b.deptno

GROUP BY b.dname

 

 

5. EMP, DEPT 테이블과 4번을 참고하여 부서이름과 직업별로 급여소계와 인원소계를 구하고

총인원과 총 급여를 구하여라 단, 부서번호, 부서이름, 직업, 급여, 인원수를 출력하시오

SELECT B.DEPTNO,b.dname,a.job

, SUM(a.sal) sal

, COUNT(a.empno) emp_count

FROM emp a, dept b

WHERE a.deptno = b.deptno

GROUP BY ROLLUP(B.DEPTNO,(b.dname,a.job))

 

 

6. 5번의 출력값에 GROUPING 함수를 사용해서 NULL값을 컬럼의 정보를 표시할 수 있는 문자열을 추가하시오

SELECT DECODE(B.DEPTNO, NULL, '전체합계', B.DEPTNO) AS 부서번호

                , DECODE(b.dname, NULL, '부서소계', b.dname) AS 부서이름

                , DECODE(a.job, NULL, '직업소계', a.job) AS 직업명

                , SUM(a.sal) sal

                , COUNT(a.empno) emp_count

FROM emp a, dept b

WHERE a.deptno = b.deptno

GROUP BY ROLLUP(B.DEPTNO,(b.dname,a.job))

 

 

7. 주문방법, 결혼여부, 성별,주문금액정보와 주문방법별, 결혼여부별, 성별별 주문합계금액을 출력하시오(group sets)

SELECT ORD.ORDER_mode 주문방법,

    DECODE (cus.marital_status, 'single', '미혼', 'married', '기혼') 결혼여부,

    DECODE (cus.gender, 'F', '여성', 'M', '남성') 성별,

    SUM (ord.order_total) 주문금액

FROM orders ord, customers cus

WHERE ord.customer_id = cus.customer_id

GROUP BY GROUPING SETS (ord.order_mode, cus.marital_status, cus.gender);

 

 

 

728x90
반응형
728x90
반응형

WITH

WITH 구문의 사용 (ORACLE9i R2이후 사용 가능)

WITH 문장은 인라인 뷰에 별칭(alias)을 부여하는데, 별칭을 부여히는 것으로 끝나지 않고

SELECT 문장에서 별칭이 부여된 인라인 뷰를 시용 기능하게 한다

 

특징

자주사용되는 쿼리를 사용하기전에 WITH절로 미리 쿼리 블록으로 정의한 후 사용한다

서브쿼리문에서 서브쿼리에 의해 메인 쿼리가 실행되기 때문에 서브쿼리문은 성능이 저하된다.

with절은 여러 개의 서브쿼리가 하나의 메인 쿼리에서 사용될 때 생기는 복잡성을 보다 간결하게 정의하여 사용함으로써 서브쿼리에서 발생할 수 있는 성능저하 현상을 방지할 수 있다

 

 

WITH <별칭1> AS ( SELECT 문장1 ),

             <별칭2> AS ( SELECT 문장2 FROM 별칭1 ),

 

SELECT 컬럼1, 걸림2,

FROM 별칭1, 별칭2

 

 

WITH 구문은 별칭2의 인라인 뷰를 FROM 절에서 바로 이전에 시용한 별칭1을 직접 사용할 수 있는 점이

WITH 구문만이 가진 고유한 특징이다.

 

 

 

728x90
반응형
728x90
반응형

RATIO_TO_REPORT

 

RATIO_TO_REPORT는 계산 대상 값 전체에 대한 현재 로우의 상대적인 비율 값을 반환하는 함수이다.

 

SELECT department_id, First_name, hire_date, salary,

                 ROUND(RATIO_TO_REPORT(salary) OVER (PARTITION BY department_id),2) * 100 AS salary_percent

FROM employees

WHERE department_id IN (30, 90);

 

RATIO_TO_REPORT 함수를 사용하면 굳이 나눗셈을 수행하지 않아도 된다

RATIO_TO_REPORT 함수는 각 로우별로 PARTITION BY 절에 명시된 그룹의 총합에 대한 비율을 반환하는 함수이다.

즉 위 쿼리에서 수행했던 나눗셈을 이 함수 하나가 담당하게 된다

 

 

 

728x90
반응형
728x90
반응형

ROLLUP

ROLLUPSELECT한 컬럼들을 GROUP BY 절과 함께 사용하게 되면 소계를 구할 수 있다

그 과정에는 CARTESIAN PRODUCT를 이용한 결과물들이란 것을 알아두자

또 한 ROLLUP의 인수는 계층 구조이므로 인수 순서가 바뀌면 수행 결과바뀌게되므로 인수의 순서에도 주의하자

 

SELECT PRESS, BOOK_TYPE, BOOK_NAME, SUM(PRICE)

FROM TEST12

GROUP BY ROLLUP(PRESS, ROLLUP(BOOK_TYPE, BOOK_NAME)

 

위의 예제를 보면 알 수 있듯이 ROLLUP은 GROUP BY절에 사용하며 그룹별로 묶어주는 개념비슷하다

그리고 이 때 소계를 출력하고 싶다면 컬럼들을 ROLLUP으로 묶어주면 간단히 출력이 가능하다

 

CUBE

CUBE는 결합이 가능한 모든 값에 대하여 다차원 집계를 생성한다

GROUPING COLUMNS이 가질 수 있는 모든 경우에 대하여 SUBTOTAL을 생성해야 하는 경우에는 CUBE를 사용

ROLLUP에 비해 시스템에 많은 부담을 주므로 사용에 주의해야 한다

 

SELECT PRESS, BOOK_TYPE, BOOK_NAME, SUM(PRICE)

FROM TEST12

GROUP BY CUBE(PRESS, BOOK_TYPE, BOOK_NAME)

 

위의 구문을 실행해보고 ROLLUP과 차이점을 생각해보자

 

 

GROUPING 함수

ROLLUP, CUBE, GROUPING SET등 새로운 그룹 함수를 지원하기위해 GROUPING 함수가 추가되었다

 

-ROLLUP이나 CUBE에 의한 소계가 계산된 결과에는 GROUPING(EXPR) = 1이 표시되고

-그 외의 결과는 GROUPING(EXPR) = 0이 표시된다

 

SELECT PRESS, GROUPING(PRESS), BOOK_TYPE, GROUPING(BOOK_TYPE),

BOOK_NAME, GROUPING(BOOK_NAME),SUM(PRICE)

FROM TEST12

GROUP BY ROLLUP(PRESS, BOOK_TYPE, BOOK_NAME)

 

출력값을 확인하자

 

 

GROUPING_ID(expr)와 GROUP ID() 함수

루트 노드의 경우는 1그 디음 계층은 2 3을 순차적으로 반환하였다. 그룹핑 쿼리에서도 그룹핑되어 추출된 각각의 로우들에 대해 그룹핑 레벨을 알 수 있는데 바로 GROUPING_IDO 함수를 시용하면 된다

 

SELECT

      DECODE (GROUPING (department_id) , 1, ' 전체부서', department_id) DEP,

      DECODE (GROUPING (job_id), 1, '합계', job_id) JOB,

      SUM (salary),

      GROUPING_ID (department_id) g_dep,

      GROUPING_ID (job_id) g_job,

      GROUPING_ID (department_id, job_id) g_total

FROM employees

WHERE department_id <= 40

GROUP BY CUBE(department_id, job_id)

ORDER BY 1,2;

 

결국 G_TOTAL 컬럼값은 0에서 3까지의 수를 반환하게 되는 것이다.

GROUPING_ID 함수의 표현식으로 부서번호와 직급 순서를 변경하면 G_TOTAL 컬럼이 반환하는 값도 달라지게 된다.

만약 위 쿼리에서 세부적인 정보는 제거하고 부서별 합계액직급별 합계액만 조회하고자 한다면 어떻게 해야 할까?

다음과 같이 HAVING 절에 GROUPING_ID() 함수사용하여 조건을 주면 된다

 

SELECT

   DECODE(GROUPING(department_id), 1, '전체부서 ', department_id) DEP,

   DECODE (GROUPING(job_id), 1, '합계', job_id) JOBS,

   SUM (salary)

FROM employees

WHERE department_id <= 40

GROUP BY CUBE (department_id, job_id)

HAVING GROUPING_ID(department_id, job_id) > 0 ORDER BY 1, 2;

 

 

GROUPING SETS(expr) 표현식

쿼리는 단순히 주문방법, 결혼여부, 성별 별로 주문금액을 집계한 것이다.

SELECT ORD.ORDER_mode 주문방법,

   DECODE (cus.marital_status, 'single', '미혼', 'married', '기혼') 결혼여부,

   DECODE (cus.gender, 'F', '여성', 'M', '남성') 성별,

   SUM (ord.order_total) 주문금액

FROM orders ord, customers cus

WHERE ord.customer_id = cus.customer_id

GROUP BY GROUPING SETS (ord.order_mode, cus.marital_status, cus.gender);

 

위의 GROUP함수의 결과값을 비교해보자

GROUPING SETS은 CUBE를 사용한 쿼리에서 개별표현식에 대한 전체합계만을 따로 추출한 것과 같다고 볼 수 있다.

 

 

 

 

 

728x90
반응형
728x90
반응형

1. SALE_HIST의 자료로 일자별 품목별로 ‘01’, ‘02’ 사업장 판매 금액합계, ‘03’, ‘04’ 사업장 판매 금액 합을 구하시오

SELECT SAEL_DATE,

                 SUM(CASE WHEN SALE_SITE BETWEEN ‘01’ AND ‘02’ THEN SALE_AMT END) AS S01

               , SUM(CASE WHEN SALE_SITE BETWEEN ‘03’ AND ‘04’ THEN SALE_AMT END) AS S02

FROM SALE_HIST

GROUP BY SALE_DATE

 

 

2. TEMP의 자료를 이용해 한 행에 5명의 사번과 성명을 보여주는 QUERY를 작성해 보라.

SELECT CEIL(ROWNUM/5) C0

,MAX(DECODE(MOD(ROWNUM, 5), 1, EMP_ID, NULL)) C1

,MAX(DECODE(MOD(ROWNUM, 5), 1, EMP_NAME, NULL)) C2

,MAX(DECODE(MOD(ROWNUM, 5), 2, EMP_ID, NULL)) C3

,MAX(DECODE(MOD(ROWNUM, 5), 2, EMP_NAME, NULL)) C4

,MAX(DECODE(MOD(ROWNUM, 5), 3, EMP_ID, NULL)) C5

,MAX(DECODE(MOD(ROWNUM, 5), 3, EMP_NAME, NULL)) C6

,MAX(DECODE(MOD(ROWNUM, 5), 4, EMP_ID, NULL)) C7

,MAX(DECODE(MOD(ROWNUM, 5), 4, EMP_NAME, NULL)) C8

,MAX(DECODE(MOD(ROWNUM, 5), 0, EMP_ID, NULL)) C9

,MAX(DECODE(MOD(ROWNUM, 5), 0, EMP_NAME, NULL)) C10

FROM TEMP

GROUP BY CEIL(ROWNUM/5)

 

 

3. TEST14와 TEST13을 이용하여 Cartesian Product을 이용하여 테이블을 조인하시오

SELECT *

FROM TEST14 , TEST13

 

 

4. 고객이 어떤 해당 상품을 받아야 하는지 TEST14와 TEST13을 이용하여 고객과 상품LIST를 출력하시오

두 테이블은 POINT에 관련이 있다

SELECT A.CUST, B.GIFT

FROM TEST14 A, TEST13 B

WHERE A.POINT > 0

AND A.POINT BETWEEN B.FPOINT AND B.TPOINT

 

 

5. TEST14와 TEST13을 이용하여 상품별로 준비되어야 할 개수를 알아보는 문장을 작성 하시오

SELECT B.GIFT, COUNT(A.CUST)

FROM TEST14 A, TEST13 B

WHERE A.POINT > 0

AND A.POINT BETWEEN B.FPOINT AND B.TPOINT

GROUP BY B.GIFT

 

 

6.고객이 가진 포인트보다 하한금액이 낮은 모든 등급의 상품을 선택할 수 있다고 할 때 갈비세트를 상품으로 받을 수 있는 고객의 고객번호, 포인트, 선물을 보여주는 QUERY를 만들어보라

SELECT *

FROM TEST14 A, TEST13 B

WHERE B.FPOINT <=  A.POINT

AND B.GIFT ='갈비세트’

 

CREATE TABLE LOGTABLE(USERID VARCHAR(10), STIME VARCHAR(5), ETIME VARCHAR(5));

 

INSERT INTO LOGTABLE

SELECT '사용자1', '07:00', '11:00'

SELECT '사용자2', '10:00', '15:00'

SELECT '사용자3', '11:00', '12:00';

 

CREATE TABLE SETIME(STIME VARCHAR(5), ETIME VARCHAR(5));

 

INSERT INTO SETIME VALUES('00:00', '01:00');

INSERT INTO SETIME VALUES('01:00', '02:00');

INSERT INTO SETIME VALUES('02:00', '03:00');

INSERT INTO SETIME VALUES('03:00', '04:00');

INSERT INTO SETIME VALUES('04:00', '05:00');

INSERT INTO SETIME VALUES('05:00', '06:00');

INSERT INTO SETIME VALUES('06:00', '07:00');

INSERT INTO SETIME VALUES('07:00', '08:00');

INSERT INTO SETIME VALUES('08:00', '09:00');

INSERT INTO SETIME VALUES('09:00', '10:00');

INSERT INTO SETIME VALUES('10:00', '11:00');

INSERT INTO SETIME VALUES('11:00', '12:00');

INSERT INTO SETIME VALUES('12:00', '13:00');

INSERT INTO SETIME VALUES('13:00', '14:00');

INSERT INTO SETIME VALUES('14:00', '15:00');

INSERT INTO SETIME VALUES('15:00', '16:00');

INSERT INTO SETIME VALUES('16:00', '17:00');

INSERT INTO SETIME VALUES('17:00', '18:00');

INSERT INTO SETIME VALUES('18:00', '19:00');

INSERT INTO SETIME VALUES('19:00', '20:00');

INSERT INTO SETIME VALUES('20:00', '21:00');

INSERT INTO SETIME VALUES('21:00', '22:00');

INSERT INTO SETIME VALUES('22:00', '23:00');

INSERT INTO SETIME VALUES('23:00', '24:00');

 

 

7. 위의 구문을 INSERT하고 출퇴근 시간대별로 몇 사람이 출퇴근했는지 사람 수와 출퇴근 시간을 출력하여라

SELECT S.STIME || '-' || S.ETIME, COUNT(*)

FROM LOGTABLE L, SETIME S

WHERE L.STIME < S.ETIME AND L.ETIME >= S.STIME

GROUP BY S.STIME || '-' || S.ETIME

ORDER BY S.STIME || '-' || S.ETIME

 

 

TEST34 활용 문제 8, 9

INSERT INTO TEST34 VALUE ('A10',4,100);

INSERT INTO TEST34 VALUE ('A11',4,110);

COMMIT;

8. 위 구문을 인설트하고 KEY_TYPE이 ‘4’인 경우에 ‘1’, ‘2’, ‘3’ 에 모두 더하고 ‘1’의 합과 ‘2’, ‘3’의 합을 구해라

선택적 조인문과 DECODE를 활용하시오

SELECT T2.R_CNT, SUM(AMT) AMT

FROM TEST34 T1, (SELECT ROWNUM R_CNT

                                       FROM TEST34

                                       WHERE ROWNUM<4) T2

WHERE T1.KEY_TYPE = DECODE(T1.KEY_TYPE, 4, T1.KEY_TYPE, T2.R_CNT)

GROUP BY T2.R_CNT;

 

 

key type amt rcnt

A01 1 10 1 true

A03 1 30 1 tur

A07 1 70 1

A09 1 90 1

A10 4 100 1 true

A11 4 110 1

410

 

A02 2 20 2

A04 2 40 2

A08 2 80 2

A10 4 100 2

A11 4 110 2

350

 

A05 3 50 3

A06 3 60 3

A10 4 100 3

A11 4 110 3

320

 

 

9. 위 구문을 인설트하고 KEY_TYPE이 ‘4’인 경우에 ‘1’, ‘2’, ‘3’ 에 모두 더하고 ‘1’, ‘2’, ‘3’의 합을 구해라

선택적 조인문과 윈도우 함수를 활용하시오 LAG()

SELECT *

FROM (SELECT DECODE(KEY_TYPE,1,'A',2,'B',3,'C') AS KEY

               , SUM(AMT) 

                 + LAG(SUM(AMT), DECODE(KEY_TYPE,1,1,2,2,3,3)) OVER (ORDER BY DECODE(KEY_TYPE,1,'A',2,'B',3,'C')

                                                                                                                                      NULLS FIRST) AS AMT

               FROM TEST34

              GROUP BY KEY_TYPE

              )

WHERE KEY IS NOT NULL

 

 

 

728x90
반응형
728x90
반응형

선택적 조인

Lateral View를 활용한 튜닝

Lateral View와 아우터조인의 개념에 대해서는 이미 언급이 되었고

이번에는Lateral View 를 이용한 튜닝에 대하여 알아보기로 한다.

 

먼저 개발자들에게 받는 질문 상위 10개 중에 항상 들어있는 질문이 있다.

"선택적으로 조인하는 기능이 오라클에 있습니까?"

필자는 항상 다음과 같이 답변한다.

"있습니다."

아래 모델을 보자.

 

이모델을 보면 고객유형(subtype) 에 따라서 개인기본으로 조인할지 사업자기본으로 조인할지 결정이 되는것이다.

물론 연락처기본은 고객기본과 항상 1:1 이다.

이런 모델에서 대부분의 개발자는 아래와 같은 SQL 을 작성한다.

 

SELECT

A.고객번호, A.고객유형,

B.취미코드, B.종교코드,

C.사업규모코드, C.종업원수,

D.대표핸드폰번호

FROM 고객기본 A, 개인기본 B, 사업자기본 C, 연락처기본 D

WHERE A.고객번호 = B.고객번호 (+)

AND A.고객번호 = C.고객번호(+)

AND A.고객번호 = D.고객번호

AND A.고객번호 = :V_고객번호; --> 고객번호에 고객유형이 개인인 고객번호 대입함.

언뜻 보기에 위의 SQL 은 아무 문제가 없어보인다.

하지만 과연 그런가?

아래 Trace 결과를 보자

 

Rows Row Source Operation

------- ---------------------------------------------------

0 STATEMENT 1 NESTED LOOPS OUTER (cr=15 pr=0 pw=0 time=225 us)

1 NESTED LOOPS OUTER (cr=11 pr=0 pw=0 time=186 us)

1 NESTED LOOPS OUTER (cr=8 pr=0 pw=0 time=145 us)

1 TABLE ACCESS BY INDEX ROWID 고객기본 (cr=4 pr=0 pw=0 time=81 us)

1 INDEX UNIQUE SCAN PK_고객기본 (cr=3 pr=0 pw=0 time=38 us)

1 TABLE ACCESS BY INDEX ROWID 연락처기본 (cr=4 pr=0 pw=0 time=47 us)

1 INDEX UNIQUE SCAN PK_연락처기본 (cr=3 pr=0 pw=0 time=26 us)

0 TABLE ACCESS BY INDEX ROWID 사업자기본 (cr=3 pr=0 pw=0 time=33 us)

0 INDEX UNIQUE SCAN PK_사업자기본 (cr=3 pr=0 pw=0 time=29 us)

1 TABLE ACCESS BY INDEX ROWID 개인기본 (cr=4 pr=0 pw=0 time=37 us)

1 INDEX UNIQUE SCAN PK_개인기본 (cr=3 pr=0 pw=0 time=25 us)

 

개인고객임에도 불구하고 사업자기본 테이블 및 인덱스에 3블럭(cr =3)씩 read 한것을 볼수 있다.

위의 SQL 은 항상 고객번호 인덱스로 개인기본과 사업자 기본을 뒤진후에 연락처기본과 조인하는 구조이다.

다시말하면 개인고객인경우도 사업자기본 테이블을 access 하고 사업자고객인 경우도 개인기본 테이블을 access 한다는 뜻이다.

 

아래처럼 ANSI SQL 을 사용하여 SQL 을 수정하면 오라클은 Lateral View 로 변환하여 비효율적인 access 를 방지한다.

고객유형에 따라서 개인일 경우 개인 기본 테이블만 access하고 고객유형이 사업자일 경우는 사업자기본 테이블만 access 한다.

 

SELECT

A.고객번호, A.고객유형,

B.취미코드, B.종교코드,

C.사업규모코드, C.종업원수,

D.대표핸드폰번호

FROM 고객기본 A

left outer join 개인기본 B

on (A.고객번호 = B.고객번호 and A.고객유형 = '1') --> 고객유형이 개인 일경우만 조인됨

 

left outer join 사업자기본 C

on (A.고객번호 = C.고객번호 and A.고객유형 = '2') --> 고객유형이 사업자 일경우만 조인됨

 

join 연락처기본 D

on (A.고객번호 = D.고객번호) --> 무조건 조인한다.

 

WHERE A.고객번호 = :V_고객번호; --> 고객번호에 고객유형이 개인인 고객번호 대입함

 

이것을 Trace 에서 차이를 비교해보면 read 한 블럭수가 차이난다.

즉 개인고객이면 사업자기본 테이블을 읽은 블럭수가 0 이고 사업자고객이면 개인기본 테이블을 읽은 블럭수가 0 이라는 뜻이다.

아래의 Trace 결과를 보자.

 

Rows Row Source Operation

------- ---------------------------------------------------

0 STATEMENT 1 NESTED LOOPS OUTER (cr=15 pr=0 pw=0 time=225 us)

1 NESTED LOOPS OUTER (cr=11 pr=0 pw=0 time=186 us)

1 NESTED LOOPS OUTER (cr=8 pr=0 pw=0 time=145 us)

1 TABLE ACCESS BY INDEX ROWID 고객기본 (cr=4 pr=0 pw=0 time=81 us)

1 INDEX UNIQUE SCAN PK_고객기본 (cr=3 pr=0 pw=0 time=38 us)

1 TABLE ACCESS BY INDEX ROWID 연락처기본 (cr=4 pr=0 pw=0 time=47 us)

1 INDEX UNIQUE SCAN PK_연락처기본 (cr=3 pr=0 pw=0 time=26 us)

0 TABLE ACCESS BY INDEX ROWID 사업자기본 (cr=0 pr=0 pw=0 time=33 us)

0 INDEX UNIQUE SCAN PK_사업자기본 (cr=0 pr=0 pw=0 time=29 us)

1 TABLE ACCESS BY INDEX ROWID 개인기본 (cr=4 pr=0 pw=0 time=37 us)

1 INDEX UNIQUE SCAN PK_개인기본 (cr=3 pr=0 pw=0 time=25 us)

 

자주 엑세스 하는 뷰를 만들때도 위와 같은 SQL 로 만들어야 할것이다.

ANSI SQL 을 사용할수 없는 구조라면 아래처럼 DECODE 함수를 활용하면 위와 같은 효과를 얻을수 있다.

 

SELECT

A.고객번호, A.고객유형,

B.취미코드, B.종교코드,

C.사업규모코드, C.종업원수,

D.대표핸드폰번호

FROM 고객기본 A, 개인기본 B, 사업자기본 C, 연락처기본 D

WHERE DECODE(A.고객유형, '1',A.고객번호) = B.고객번호(+) --> 고객유형이 개인일경우만 조인됨

AND DECODE(A.고객유형, '2',A.고객번호) = C.고객번호(+) --> 고객유형이 사업자 일경우만 조인됨

AND A.고객번호 = D.고객번호

AND A.고객번호 = :V_고객번호;

 

 

 

 

 

 

 

728x90
반응형
728x90
반응형

부등호 조인

이번 장은 기본 개념 부분에서 다룬 조인에 대한 심화학습이다

 

1. 부등호 조인에 대한 복습

2. 조인을 이용해 해결하는 방법과 서브쿼리로 해결하는 방법을 제시한다

   두가지 해법의 비교를 통해 언제 조인과 서브쿼리가 같은 결과를 낼 수 있는지를 알아보기 바란다

3. 경우에 따라 선택적으로 조인을 하는 문제를 다뤄본다

 

참고로 부등호 조인은 Cartesian Product와 많은 관련이 있으므로 기본적인 의미를 알아야만 이해하기가 쉽다

Cartesian Product WHERE절에 조인조건 없이 조인하는 경우 테이블 ROW 개수만큼 데이터가 복제되는 현상이다.

 

부등호 조인은 조인을 할 경우 BETWEEN, LIKE, 부등호 같은 연산자 조인이 필요할 때 사용한다

부등호 조인이 일어나기전 Cartesian Product로 조인이 일어난다 그리고 where절의 조건문에 의해 행마다 조건에 부합하는 행들이 출력되는 것이다

(이것은 부등호조인만이 아니라 테이블을 조인할 때에는

select문 순서에 의해 모든 테이블이 Cartesian Product이 일어나는 것을 알수 있다)

이 때 부등호 조인은 한 개의 테이블의 컬럼 값이 다른 테이블 두 개의 컬럼에 수치상으로 포함될 때 두 테이블은 하나의 테이블로 합쳐지고 그 합쳐질 때

두 개를 부등호 조인으로 행마다 조건절을 주어 거기에 해당하는 행만 출력하는 조건이다

 

- 부등호조인 단점

cartesian productjoin을 하면서 부등호 조건을 동시에 비교하기 때문에

칼럼이 많을 수록 연산속도가 저하

100행 연산 0.38 / 1000행 연산 16.80

 

728x90
반응형
728x90
반응형

27 사번, 이름, 부서번호, 급여를 출력하고 분석함수를 사용한 컬럼에 해당 사원과 이전 사원 급여액 합계를 구하여라

SELECT EMP_ID, EMP_NAME, DEPT_CODE, SALARY

          ,SUM(SALARY) OVER (ORDER BY SALARY

                                       ROWS 1 PRECEDING ) AS 이전사원급여합계

FROM TEMP

 

 

28, 사번, 이름, 부서번호, 급여를 출력하고 분석함수를 사용한 컬럼에 해당 부서별 사원과 이전 사원 급여액 합계를 구하여라

SELECT EMP_ID, EMP_NAME, DEPT_CODE, SALARY

          ,SUM(SALARY) OVER (PARTITION BY DEPT_CODE

                                       ORDER BY SALARY

                                       ROWS 1 PRECEDING ) AS 부서별이전사원급여합계

FROM TEMP

 

 

29 사번, 이름, 부서번호, 급여를 출력하고 분석함수를 사용한 컬럼 3개를 생성하여 첫번째는 사원들의 급여의 총액

두 번째는 사원들의 누적급여총액 그리고 또 다른 하나의 세 번째는 두 번째를 역순으로 표시하여라

SELECT EMP_ID, EMP_NAME, DEPT_CODE, SALARY

          ,SUM(SALARY) OVER (ORDER BY SALARY

                                       ROWS BETWEEN UNBOUNDED PRECEDING

                                       AND UNBOUNDED FOLLOWING ) AS 부서사원급여합계

 

         ,SUM(SALARY) OVER (ORDER BY SALARY

                                      ROWS UNBOUNDED PRECEDING ) AS 부서사원누적급여합계

 

         ,SUM(SALARY) OVER (ORDER BY SALARY DESC

                                      ROWS BETWEEN CURRENT ROW

                                      AND UNBOUNDED FOLLOWING ) AS 부서사원누적역순급여합계

FROM TEMP

 

 

30 29번 결과 값을 참고하여 사원이 아닌 부서별로 사원들의 총액, 부서별 사원들의 누적급여액 등을 구하여라

SELECT EMP_ID, EMP_NAME, DEPT_CODE, SALARY

                ,SUM(SALARY) OVER ( PARTITION BY DEPT_CODE

                                                            ORDER BY SALARY

                                                            ROWS BETWEEN UNBOUNDED PRECEDING

                                                            AND UNBOUNDED FOLLOWING ) AS 부서사원급여합계

 

               ,SUM(SALARY) OVER ( PARTITION BY DEPT_CODE

                                                            ORDER BY SALARY

                                                            ROWS UNBOUNDED PRECEDING ) AS 부서사원누적급여합계

 

                ,SUM(SALARY) OVER ( PARTITION BY DEPT_CODE

                                                            ORDER BY SALARY DESC

                                                            ROWS BETWEEN CURRENT ROW

                                                            AND UNBOUNDED FOLLOWING ) AS 부서사원누적역순급여합계

FROM TEMP

 

 

31 일자별 사업장별 매출액과 사업장별 매출액의 3일 이동평균 금액을 구하라 (SALE_HIST)

31번 문제는 PARTITION, GROUP, RANGE 활용 문제이다

SELECT SALE_DATE, SALE_SITE, SUM(SALE_AMT),

                 ROUND(AVG(SUM(SALE_AMT)) OVER( PARTITION BY SALE_SITE

                                                                                              ORDER BY SALE_DATE

                                                                                              RANGE INTERVAL '2' DAY PRECEDING)) AS 이동평균

FROM SALE_HIST

GROUP BY SALE_DATE, SALE_SITE

 

 

32 각 ROW의 판매액, 동일일자/ 동일품목의 최대판매액, 최대판매액사업장, 해당 사업장 최소판매액, 최소판매액 사업장을 구하여라

SELECT SALE_DATE, SALE_ITEM, SALE_AMT, SALE_SITE

          ,FIRST_VALUE(SALE_AMT) OVER( PARTITION BY SALE_DATE, SALE_ITEM

                                                    ORDER BY SALE_AMT DESC

                                                    ROWS BETWEEN UNBOUNDED PRECEDING

                                                    AND UNBOUNDED FOLLOWING ) AS 최고판매액

 

         ,FIRST_VALUE(SALE_SITE) OVER( PARTITION BY SALE_DATE, SALE_ITEM

                                                   ORDER BY SALE_AMT DESC

                                                   ROWS BETWEEN UNBOUNDED PRECEDING

                                                   AND UNBOUNDED FOLLOWING ) AS 최고판매사업장

 

        ,LAST_VALUE(SALE_AMT) OVER( PARTITION BY SALE_DATE, SALE_ITEM

                                                 ORDER BY SALE_AMT DESC

                                                 ROWS BETWEEN UNBOUNDED PRECEDING

                                                 AND UNBOUNDED FOLLOWING ) AS 최저판매액

 

        ,LAST_VALUE(SALE_SITE) OVER( PARTITION BY SALE_DATE, SALE_ITEM

                                                 ORDER BY SALE_AMT DESC

                                                 ROWS BETWEEN UNBOUNDED PRECEDING

                                                 AND UNBOUNDED FOLLOWING ) AS 최저판매사업장

FROM SALE_HIST;

 

 

33 SALE_HIST의 자료를 이용하여‘01’ 사업장‘ PENCIL’ 품목의 일자별 누적 판매금액을 구하여라

SELECT SALE_DATE, SALE_SITE, SALE_ITEM, SALE_AMT,

          SUM(SALE_AMT) OVER ( ORDER BY SALE_DATE

                                          RANGE INTERVAL '5' DAY PRECEDING) AS 누적합계

FROM SALE_HIST

WHERE SALE_ITEM = 'PENCIL'

AND SALE_SITE = '01'

 

 

34 품목별/일자별 과거 판매매액을 모두 이용하는 이동평균값을 구하라

SELECT SALE_ITEM , SALE_DATE, SUM(SALE_AMT)

          ,AVG(SUM(SALE_AMT)) OVER( PARTITION BY SALE_ITEM

                                                 ORDER BY SALE_DATE

                                                 ROWS UNBOUNDED PRECEDING ) AS 품목일자별이동평균

FROM SALE_HIST

GROUP BY SALE_ITEM , SALE_DATE

 

 

35 SALE_HIST의 자료를 이용하여 “01”사업장 PENCIL 품목에 대해 일자별 매출액과 전일 매출, 당일과 전일의 매출액 차이를 구하시오

SELECT SALE_DATE, SALE_SITE, SALE_ITEM, SALE_AMT

          , LAG(SALE_AMT,1) OVER ( ORDER BY SALE_DATE) AS 전일매출

          , SALE_AMT - LAG(SALE_AMT,1) OVER ( ORDER BY SALE_DATE) AS 전일매출차액

FROM SALE_HIST

WHERE SALE_ITEM = 'PENCIL'

AND SALE_SITE = '01’

 

 

 

 

 

 

 

728x90
반응형
728x90
반응형

 

21 TEMP의 자료에서 ROWNUM을 채취해 값이 5와 10 사이에 있는 행의 ROWNUM, 사번, 이름을 조회하시오

SELECT NUM, EMP_ID, EMP_NAME

FROM ( SELECT ROWNUM NUM, EMP_ID, EMP_NAME FROM TEMP)

WHERE NUM > 4 AND NUM <11

 

 

22

INSERT INTO TDEPT ( DEPT_CODE, DEPT_NAME, PARENT_DEPT, USE_YN, AREA, BOSS_ID ) VALUE

(‘000000’, ‘사장실’, ‘ ’, ‘Y’, ‘서울’, ‘ ’)

 

위의 구문을 COMMIT 하고

기존 테이블에 최상위 부서로 지정되어있는 경영지원 부서를 사장실로 변경한다

UPDATE TDEPT

SET PARENT_DEPT = '000000'

WHERE DEPT_CODE=PARENT_DEPT;

 

 

23 사장실을 기준으로 계층구조 전개를 하여 출력하시오 (LPAD를 활용)

SELECT LPAD(DEPT_NAME, LEVEL*12,' ')AS 부서이름

,DEPT_CODE

,PARENT_DEPT

FROM TDEPT

START WITH DEPT_CODE='000000'

CONNECT BY PRIOR DEPT_CODE=PARENT_DEPT

 

 

24 CA0001의 하위 부서를 모두 제거 하고 계층구조 전개를 하여 출력하시오 (LPAD를 활용)

SELECT LPAD(DEPT_NAME, LEVEL*12,' ')AS 부서이름, DEPT_CODE, PARENT_DEPT

FROM TDEPT

CONNECT BY PRIOR DEPT_CODE=PARENT_DEPT

AND DEPT_CODE <> ‘CA0001’

START WITH DEPT_CODE='000000'

 

CONNECT 와 조건절의 순서를 어디에 배치하는가에 따라 그 느낌도 구조도 달라진다

"CONNECT BY PRIOR DEPT_CODE=PARENT_DEPT" 

->  왼쪽의 구문은 CONNECT가 일어나고 그다음

 

"AND DEPT_CODE <> ‘CA0001’" 

->  CONNECT에 대한 조건절을 하나 더 추가하는 느낌으로 CONNECT가 생성이되고 나서 조건절에 대한 계층에 의미를 부여한다 그래서 CA0001에 해당하는 하위부서 까지 모두 제거된다

 

============================================================================

 

SELECT LPAD(DEPT_NAME, LEVEL*12,' ')AS 부서이름, DEPT_CODE, PARENT_DEPT

FROM TDEPT

WHERE DEPT_CODE <> ‘CA0001’

CONNECT BY PRIOR DEPT_CODE=PARENT_DEPT

START WITH DEPT_CODE='000000'

 

 

테이블의 조건절로 사용되며 테이블에서 먼저 CA0001을 제거한 후

WHERE DEPT_CODE <> ‘CA0001’ 

->  CONNECT를 실시하게 된다 그래서 CA0001만 없어지고

 

CONNECT BY PRIOR DEPT_CODE=PARENT_DEPT 

->  CA0001의 하위부서는 그대로 남겨지게된다

 

 

25 어느 한 사원이 영업2(CD0001)부서에 근무하고 있다 자기의 상위 부서를 출력하시오

(계층구조 전개로출력)

SELECT LEVEL, LPAD(DEPT_NAME, LEVEL*12,' ') AS 부서이름 ,DEPT_CODE ,PARENT_DEPT

FROM TDEPT

START WITH DEPT_CODE = 'CD0001'

CONNECT BY PRIOR PARENT_DEPT=DEPT_CODE

 

 

26 부서별로 부서장(BOSS_ID)과 성명(EMP_ID)를 부서의 전개에 의해 도출된 결과와 같은 형식으로 출력하시오

SELECT A.LEV, A.EMP_NAME, B.BOSS, B.DEPT_CODE, B.DEPT_NAME

FROM TEMP A,

         (SELECT LEVEL LEV, LPAD(BOSS_ID, LEVEL*12,' ') BOSS

                    ,DEPT_CODE, DEPT_NAME

          FROM TDEPT

          START WITH DEPT_CODE = '000000'

          CONNECT BY PRIOR DEPT_CODE= PARENT_DEPT

          ) B

WHERE A.EMP_ID(+)=B.BOSS

 

 

728x90
반응형
728x90
반응형

SALE_HIST의 자료를 이용하여 사업장의 상품 판매금액과 아이템순으로 일자별 판매누적금액을 출력하시오

SELECT SALE_DATE, SALE_SITE, SALE_ITEM, SALE_AMT,

          SUM(SALE_AMT) OVER (PARTITION BY SALE_DATE ORDER BY SALE_ITEM

                                          ROWS UNBOUNDED PRECEDING) AS 누적합계

FROM SALE_HIST

 

 

SALE_HIST의 자료를 이용하여 사업장의 상품 판매금액과 일자순으로 아이템별 판매누적금액을 출력하시오

SELECT SALE_DATE, SALE_SITE, SALE_ITEM, SALE_AMT,

          SUM(SALE_AMT) OVER (PARTITION BY SALE_ITEM ORDER BY SALE_DATE

                                           ROWS UNBOUNDED PRECEDING) AS 누적합계

FROM SALE_HIST

 

 

SALE_HIST의 자료를 이용하여 사업장의 상품 판매금액과 일자와 아이템별 판매누적금액을 출력하시오

SELECT SALE_DATE, SALE_SITE, SALE_ITEM, SALE_AMT,

          SUM(SALE_AMT) OVER (PARTITION BY SALE_ITEM, SALE_DATE ORDER BY SALE_AMT

                                           ROWS UNBOUNDED PRECEDING) AS 누적합계

FROM SALE_HIST

 

 

SALE_HIST의 자료를 이용하여 ‘01 사업장‘ ’PENCIL’ 품목의 아이템별 판매금액과 누적 판매금액을 구하여라

SELECT SALE_DATE, SALE_SITE, SALE_ITEM, SALE_AMT,

          SUM(SALE_AMT) OVER (PARTITION BY SALE_ITEM ORDER BY SALE_DATE

                                           RANGE INTERVAL '5' DAY PRECEDING) AS 누적합계

FROM SALE_HIST

WHERE SALE_ITEM = 'PENCIL'

AND SALE_SITE = '01’

 

 

일자별 사업장별 매출액과 사업장별 매출액의 3일 이동평균 금액을 구하라 (SALE_HIST)

SELECT SALE_DATE, SALE_SITE, SUM(SALE_AMT),

          ROUND(AVG(SUM(SALE_AMT)) OVER (PARTITION BY SALE_SITE ORDER BY SALE_DATE

                                                            RANGE INTERVAL '2' DAY PRECEDING) AS 이동평균

FROM SALE_HIST

GROUP BY SALE_DATE, SALE_SITE

 

 

EMP테이블에서 직속상관 MGR, 자기이름 ENAME, 자기급여 SAL 출력하여라 단, 같은 MGR별 직속부하들 중 최고 급여를 받는 사람들의 정보를 출력할 것

SELECT MGR, ENAME, SAL

FROM (SELECT MGR, ENAME, SAL,

                    MAX(SAL) OVER (PARTITION BY MGR) AS IV_MAX_SAL

           FROM EMP)

WHERE SAL = IV_MAX_SAL;

 

 

A_TB의 자료를 이용하여 매월의 A_OUT과 분기별 누계를 구하시오

SELECT A_MON, A_OUT,

          SUM(A_OUT) OVER (PARTITION BY TO_CHAR(TO_DATE(A_MON,'YYYYMM'),'Q')

                                      ORDER BY TO_DATE(A_MON,'YYYYMM')

                                      RANGE INTERVAL '2' MONTH PRECEDING) AS C1

FROM A_TB

 

 

TEST02의 20010901부터 20010911까지의 자료를 이용해 해당 일자 보다 작거나 같은 날의 환율을 순서대로 6개까기지 보여주는 QUERY를 만들어 보자

SELECT CDATE, AMT, CRATE

          , LAG(CRATE,1) OVER (ORDER BY CDATE) AS "-1 DAY"

          , LAG(CRATE,2) OVER (ORDER BY CDATE) AS "-2 DAY"

          , LAG(CRATE,3) OVER (ORDER BY CDATE) AS "-3 DAY"

          , LAG(CRATE,4) OVER (ORDER BY CDATE) AS "-4 DAY"

          , LAG(CRATE,5) OVER (ORDER BY CDATE) AS "-5 DAY"

          , LAG(CRATE,6) OVER (ORDER BY CDATE) AS "-6 DAY"

FROM TEST02

WHERE CDATE BETWEEN '20010901' AND '20010911’

 

 

TEST02의 20010901부터 20010911까지의 자료를 이용해 해당 일자 보다 크거나 같은 날의 환율을 순서대로 6개까기지 보여주는 QUERY를 만들어 보자

SELECT CDATE, AMT, CRATE

, LEAD(CRATE,1) OVER (ORDER BY CDATE) AS "+1 DAY"

, LEAD(CRATE,2) OVER (ORDER BY CDATE) AS "+2 DAY"

, LEAD(CRATE,3) OVER (ORDER BY CDATE) AS "+3 DAY"

, LEAD(CRATE,4) OVER (ORDER BY CDATE) AS "+4 DAY"

, LEAD(CRATE,5) OVER (ORDER BY CDATE) AS "+5 DAY"

, LEAD(CRATE,6) OVER (ORDER BY CDATE) AS "+6 DAY"

FROM TEST02

WHERE CDATE BETWEEN '20010901' AND '20010911'

 

 

TEST02 테이블을 이용해서 20010905부터 20010910까지 데이터를 출력하되 널값은 제외하고 출력하시오

현재일자의 금액에 전일 환율을 곱한 환산금액을 구하여 현재 일자, 현재 금액, 전일 환율, 환산금액을 출력하여라

SELECT C_DATE, C_AMT, 금일환율, 전일환율, 환산금액

FROM (SELECT CDATE C_DATE, AMT C_AMT, CRATE 금일환율

                    ,LAG(CRATE,1) OVER(ORDER BY CDATE) AS 전일환율

                    ,AMT*LAG(CRATE,1) OVER(ORDER BY CDATE) AS 환산금액

          FROM TEST02

          WHERE CDATE BETWEEN '20010904' AND '20010910'

          )

WHERE 환산금액 IS NOT NULL

 

 

TEMP의 EMP_ID를 이용해 자신의 사번과 자신보다 한 단계 빠른 사번을 가진 직원의 사번과 성명을 보여주는 QUERY를 만들어라 ( LAG(), MIN(), MAX() 함수 활용을 생각해보자 )

SELECT EMP_ID, EMP_NAME

          ,LAG(EMP_ID,1) OVER (ORDER BY EMP_ID) AS 이전사원사번

          ,LAG(EMP_NAME,1) OVER (ORDER BY EMP_ID) AS 이전사원이름

FROM TEMP

 

,MIN(EMP_ID) OVER (ORDER BY EMP_ID

                             ROWS BETWEEN 1 PRECEDING

                                       AND 1 PRECEDING) AS 전사원사번

 

,MAX(EMP_ID) OVER (ORDER BY EMP_ID

                              ROWS BETWEEN UNBOUNDED PRECEDING

                                        AND 1 PRECEDING) AS 이전사원사번

 

 

TEMP의 자료를 이용하여 자신의 사번, 성명, SALARY를 읽고, 자신을 포함한 이후 사번 중 SALARY가 가장 큰 금액을 함께 보여라

SELECT EMP_ID, EMP_NAME, SALARY

          ,MAX(SALARY) OVER (ORDER BY EMP_ID

                                       ROWS BETWEEN CURRENT ROW

                                                 AND UNBOUNDED FOLLOWING ) AS 이후최고금액

FROM TEMP

 

 

728x90
반응형
728x90
반응형

연습문제

 

11 오늘이 몇일인지 출력하시오

SELECT TO_CHAR(SYSDATE,‘DD’) FROM DUAL

 

 

12 오늘이 무슨요일인지 출력하시오

SELECT TO_CHAR(SYSDATE,‘DAY’) FROM DUAL

 

 

13 위의 11번과 12을 합쳐서 출력하시오 결과 예제 -> 03목요일

SELECT TO_CHAR(SYSDATE,‘DD’) || TO_CHAR(SYSDATE,‘DAY’) FROM DUAL

 

 

14 요일마다 LOGIN 암호를 자동으로 바꿔주는 프로그램을 만든다고 가정하자 월요일엔 해당일자에 01을 붙여서 4자리를 만들고 화요일엔 11, 수요일엔 21, 목요일엔 31, 금요일엔 41, 토요일엔 51, 일요일엔 61, 붙여서 만들고자한다

SELECT TO_CHAR(SYSDATE,'DD') || DECODE(TO_CHAR(SYSDATE,'DAY'), 'MONDAY', 11, 'TUESDAY', 12,

                              'WEDNESDAY', 13, 'THURSDAY', 14, 'FRIDAY', 15, 'SATURDAY', 16, 'SUNDAY', 17)

FROM DUAL

 

 

15 LECTURE 테이블에서 LEC_TIME과 LEC_POINT를 비교해보자 비교한 결과를 이용해 LEC_TIME이 크면 ’실험과목‘ LEC_POINT가 크면 ’기타과목‘, 둘이 같으면 ’일반과목’으로 값을 돌려받고자 한다.

SELECT DECODE(SIGN(LEC_TIME-LEC_POINT), 0, ‘일반과목’, 1, ‘실험과목’, -1, ‘기타과목’) FROM LECTURE

 

 

16 강의 시간과 학점이 같거나 강의시간이 학점보다 작으면 ‘일반과목’을 돌려받고 강의시간이 학점보다 큰경우만‘실험과목’을 돌려받고자 한다 두가지 방법 SIGN, LEAST를 사용하자

SELECT LEC_ID, DECODE(LEAST(LEC_TIME,LEC_POINT), LEC_TIME, '일반과목', '실험과목') FROM LECTURE

 

SELECT LEC_ID, DECODE(SIGN(LEC_TIME-LEC_POINT), 0, '일반과목', -1, '일반과목', 1, '실험과목') FROM LECTURE

 

 

17 LECTURE 테이블의 자료중 LEC_TIME과 LEC_POINT가 같다라는 조건을 만족하고 LEC_TIME=3 인 자료는 옆에 ‘중요과목’이라는 비고를 붙이고자한다

SELECT LEC_ID, DECODE(LEC_TIME, LEC_POINT, DECODE(LEC_TIME,3, '중요과목')) FROM LECTURE

 

 

18. TEMP의 행을 3개씩 묶어 하나의 번호를 부여하고, 해당 ROWNUM을 3으로 나눈 나머지가 1이면 사번 아니면 NULL, 또 한 번은 1이면 성명 아니면 NULL 이렇게 순차적으로 사번, 성명을 출력하고 이어서 나머지가 2, 0인 경우도 같은 조건으로 출력하여라

SELECT CEIL(ROWNUM/3) C0

,DECODE(MOD(ROWNUM,3), 1, EMP_ID, NULL) C1

,DECODE(MOD(ROWNUM,3), 1, EMP_ID, NULL) C2

,DECODE(MOD(ROWNUM,3), 2, EMP_ID, NULL) C3

,DECODE(MOD(ROWNUM,3), 2, EMP_ID, NULL) C4

,DECODE(MOD(ROWNUM,3), 0, EMP_ID, NULL) C5

,DECODE(MOD(ROWNUM,3), 0, EMP_ID, NULL) C6

FROM TEMP

 

 

19 위 예문의 결과를 이용하여 한 행에 사번 성명을 3명씩 보여주는 SQL을 작성하자 (열을 행으로 바꾸는 문제)

SELECT CEIL(ROWNUM/3) C0

, MAX(DECODE(MOD(ROWNUM,3), 1, EMP_ID, NULL)) C1

, MAX(DECODE(MOD(ROWNUM,3), 1, EMP_NAME, NULL)) C2

, MAX(DECODE(MOD(ROWNUM,3), 2, EMP_ID, NULL)) C3

, MAX(DECODE(MOD(ROWNUM,3), 2, EMP_NAME, NULL)) C4

, MAX(DECODE(MOD(ROWNUM,3), 0, EMP_ID, NULL)) C5

, MAX(DECODE(MOD(ROWNUM,3), 0, EMP_NAME, NULL)) C6

FROM TEMP

GROUP BY CEIL(ROWNUM/3)

 

 

20 사원 테이블에서 사원을 골라 해당 사원의 연봉이 동일한 직급을 가진 사원의 평균 연봉보다 많은 사원을 출력하라

SELECT A.SALARY, A.EMP_ID, A.EMP_NAME ,B.AVG_SAL

FROM TEMP A ,(SELECT LEV, AVG(SALARY) AVG_SAL

                                  FROM TEMP

                                  GROUP BY LEV ) B

WHERE A.LEV = B.LEV

AND A.SALARY > B.AVG_SAL

 

 

 

728x90
반응형
728x90
반응형

1. TEMP와 TCOM에 존재하는 사번의 교집합을 구한후, TEMP에서 TCOM에 존재하는 사번을 제외시킨 차집합을 구하고, 두결과의 합집합을 구해보자

(SELECT EMP_ID FROM TEMP INTERSECT SELECT EMP_ID FROM TCOM) UNION

(SELECT EMP_ID FROM TEMP MINUS SELECT EMP_ID FROM TCOM);

 

 

2. TEMP 테이블과 TCOM의 행의 개수를 카테시안 조인으로 구하여라

SELECT COUNT(*) FROM TEMP, TCOM

 

 

3. TEMP에서 사번, 성명, 부서코드, 부서명을 출력하시오

SELECT A.EMP_ID, A.EMP_NAME, A.DEPT_CODE, B.DEPT_NAME

FROM TEMP A, TDEPT B

WHERE B.DEPT_CODE = A.DEPT_CODE;

 

 

4. TEMP에 존재하는 직원들 중 과장직급을 가질만한 나이에 포함되는 사람이 누구인지 출력하시오

( EMP_LEVE, TEMP )

SELECT B.EMP_ID,B.BIRTH_DATE FROM EMP_LEVEL A, TEMP B

WHERE B.BIRTH_DATE BETWEEN ADD_MONTHS(SYSDATE,-1* TO_AGE*12)

                                                           AND ADD_MONTHS(SYSDATE,-1* FROM_AGE*12)

                                                           AND B.LEV='대리';

 

 

5. TEMP와 EMP_LEVE를 이용해 과장 직급의 연봉 상한/하한 범위내에 있는 직원 사번 성명 직급 SALARY를 출력

SELECT A.EMP_ID, A.EMP_NAME, A.LEV, A.SALARY

FROM TEMP A, EMP_LEVEL B

WHERE A.SALARY BETWEEN FROM_SAL AND TO_SAL

AND B.LEV='과장';

 

 

6. 사번, 이름 SALARY, 연봉 상한 금액을 보고자 한다. TEMP와 EMP_LEVEL을 조인하여 결과를 보여주되 연봉의 상하한이 등록되어있지않은 수습사원은 사번, 이름 SALARY까지만 출력하는 QUERY를 구성해보자

SELECT A.EMP_ID, A.EMP_NAME, A.SALARY, B.TO_SAL

FROM TEMP A, EMP_LEVEL B

WHERE B.LEV(+)=A.LEV;

 

 

7. TEMP의 자료를 이용해 NON-EQUI JOIN이면서 SELF JOIN이고 QUTER조인인 QUREY를 하나 만들어 보자

사번, 성명, 생일, 자신보다 생일이 빠른 사람의 수를 읽어와 자신보다 생일이 빠른 사람의 수로 정렬하여 출력

SELECT A.EMP_ID, A.EMP_NAME,A.BIRTH_DATE, COUNT(B.BIRTH_DATE)

FROM TEMP A, TEMP B

WHERE B.BIRTH_DATE(+)<A.BIRTH_DATE

GROUP BY A.EMP_ID, A.EMP_NAME, A.BIRTH_DATE

ORDER BY COUNT(B.BIRTH_DATE)

 

 

8. TEMP에 속한 수습사원만 순번을 붙여 출력하시오. 단 5번까지만 출력하시오

SELECT ROWNUM, EMP_ID, EMP_NAME

FROM TEMP

WHERE EMP_ID > 0 AND LEV=’수습‘ AND ROWNUM <= 5

 

 

9. TEMP 테이블의 자료를 이용하여 SELECT 결과를 3개행씩 묶어 하나의 번호를 부여하는 SQL을 만들어보자

SELECT ROWNUM, CEIL(ROWNUM/3), EMP_ID, EMP_NAME FROM TEMP WHERE EMP_ID>0

 

10. 강의 ID와 주당 강의 시간과 학점이 같으면 일반으로 표시하고 아니면 특별로 출력하시오

SELECT LEC_ID, DECODE(LEC_TIME, LEC_POINT,’일반‘,’특별’) FROM LECTURE

 

 

728x90
반응형
728x90
반응형

 

DECODE의 기본적인 기능은 프로그래밍 언어의 IF 문을 SQL 문장으로 사용하기 위하여 만들어진 오라클이다

FROM 절만 빼고 어디서나 사용할 수 있고 IF문의 전형적인 형태를 분류하여 DECODE문으로 나누어 사용하자

 

1.DECODE의 사용(등순 등호 비교)

IF A = B THEN

RETURN ‘T’;

END IF;

SELECT DECODE(A,B,‘T’,NULL) AS COL1

FROM TABLE이름

 

2 DECODE의 사용(등호비교 + ELSE)

IF A=B THEN

RETURN ‘T

ELSE

RETURN ‘F

END IF

SELECT DECODE(A,B,‘T’,‘F’) AS COL1

FROM TABLE이름

 

3 DECODE의 사용(ELSEIF 분기되는 등호비교)

 

IF A=B THEN

RETURN 1

ELSEIF A=C THEN

RETURN 2

ELSE

RETURN 3

END IF

SELECT DECODE(A, B, 1, C, 2, 3)

FROM TABLE이름

4 DECODE의 사용 (부등호 비교)

 

SIGN, LEAST, GREATEST를 사용하여 등호비교를 한다

SIGN 은 주어진 값이 음수인지, 양수인지 아니면 0인지를 나타낸다

LEAST 주어진 값들 중 최소값을 돌려준다

GREATEST는 주어진 값들중 최대값을 돌려준다

 

IF A>B = 0 THEN

RETURN ‘일반

ELSEIF 1 THEN

RETURN ’실험

END IF

SELECT DECODE(

          SIGN(A,B), 0, ‘일반‘,1, ’실험‘,-1, ’기타과목‘)AS TY

5 DECODE의 사용(OR 또는 IN 비교)

IF A IN (B, C, D) THEN

RETURN ‘T’

ELSE

RETURN ‘F’

END IF

 

IF A=B OR A=C THEN

RETURN ‘T’

ELSE

RETURN ‘F’

END IF

 

첫 번째 IF

DECODE(A, B,‘T’, C, ‘T’, D,‘T’,‘F’)

 

 

 

두 번째 IF

 

DECODE(A, B, ‘T’, C, ‘T’, ‘F’)

 

6 DECODE의 사용(AND 비교) - AND비교는 리턴 부분에 다시 IF(DECODE)이 사용된다는 것이 핵심

 

IF A=B AND A=C THEN

RETURN ‘T’

ELSE

RETURN ‘F’

END

 

DECODE(A, B, DECODE(A, C, ‘T’, ‘F’), ‘F’)

 

 

728x90
반응형
728x90
반응형

WINDOW 함수

 

WINDOW 함수는 AVG, COUNT, SUM, MAX, MIN만 사용 가능

 

윈도우 함수( ) OVER (

             PARTITION BY 절                              PARTITION BY 절에 명시된 그룹을 좀 더 세부적으로 그룹핑 가능

             ORDER BY 절 [ASC|DESC]             

             ROWS | RANGE

             BETWEEN UNBOUNDED PRECEDING | n PRECEDING | CURRENT ROW

             AND UNBOUNDED FOLLOWING | n FOLLOWING | CURRENT ROW

 

 

OVER - 쿼리 RESULT SET을 이용해 동작하는 함수라는 구분

 

PARTITION BY - RESULT SET을 VALUE EXPRESS 에 지정된 값에 근거하여 분활하는 역할 수행

 

( ) - 안에 기술된 ORDER BY는 RESULT SET에 순위를 부여할 때 정렬기준을 표시하는 부분

 

ORDER BY – 각 PARTITION 내에서 DATA 각 어떤 값을 기준으로 정렬될 것인가를 지정

 

[NULLIS FIRST | NULLS LAST] - NULL이 포함된 ROW가 순서상 제일 앞이나 제일 뒤에 위치할 것인지 지정

 

ROWS | RANGE - 자료의 물리적 순서를 이용(ROWS)할 것인지 논리적 순서(RANGE)를 이용할 것인지 결정

 

 

BETWEEN ~ AND ~ - 자료의 범위를 결정한다.

- UNBOUNDED PRECEDING PARTITION의 첫 번째 로우에서 윈도우가 시작한다.

 

- UNBOUNDED FOLLOWING PARTITION의 마지막 로우에서 윈도우가 시작한다

 

- CURRENT ROW 현재 ROW를 시작 값

 

- ROWS 1 PRECEDING 1행 이전 행을 말한다

 

- ROWS 2 FOLLOWING 2행 이후 행을 말한다

 

- RANGEINTERVAL을 꼭 붙여서 숫자 ‘ ’ 안에 표시해야 한다

 

- RANGE INTERVAL ‘2’ DAY PRECEDING 3일 이동 합계

 

 

윈도우함수의 종류

FIRST_VALUE() - 윈도우 함수의 정렬이 끝이나고 제일 앞에 위치하는 ROW의 값들을 읽어올 때 사용.

 

LAST_VALUE() - 윈도우 함수의 정렬이 끝이나고 제일 뒤에 위치하는 ROW의 값들을 읽어올 때 사용.

 

RATIO_TO_REPORT - 함수가 전체대비 해당 ROW의 값이 차지하는 비율을 구해주고 있다.

 

LAG(컬럼, 원하는 행) - 해당 행의 앞에 몇 번째 행을 참조할 것인지 지정 가능

 

LEAD(컬럼, 원하는 행) - 해당 행의 뒤에 몇 번째 행을 참조할 것인지 지정 가능

 

 

728x90
반응형
728x90
반응형

분석 함수

RANK() OVER( [PARTITION BY <VALUE EXPRESS>]

                              ORDER BY <VALUE EXPRESS> [ASC | DESC]

                              [NULLIS FIRST | NULLS LAST]

                            )

 

활용 예문

SELECT 사원이름, 사원번호, 평균급여, 부서번호 같은 등수 7등이 2명 있다면

 

RANK() OVER (PARTITION BY 부서번호 DENS_RANK()는 8등이 되며

                              ORDER BY 평균급여 ASC) AS 순위 RANK()는 9등이 된다

FROM 사원테이블

GROUP BY DEPT_CODE, EMP_ID, EMP_NAME;

 

OVER – 해당함수가 QUERY의 RESULT SET을 이용하여 동작하는 함수라는 표시

 

( ) 안에 기술된 ORDER BY는 RESULT SET에 순위를 부여할 때 정렬기준을 표시 해주는 부분

 

ORDER BY – 각 PARTITION 내에서 DATA 각 어떤 값을 기준으로 정렬될 것인가를 지정

 

[NULLIS FIRST | NULLS LAST] NULL이 포함된 ROW가 순서상 제일 앞이나 제일 뒤에 위치할 것인지 지정

 

 

PARTITION BY의 기능

전체 SELECT 문에서 GROUP BY ROLLUP으로 특정 칼럼을 ID, 부서번호부서별의 소계와 ID별 소계가 출력이된다

그렇게 출력된 소계들을 다시 순위를 줄수 있는데

그 방법은 RANK() OVER (PARTITION BYGROUPING 으로 ID 와 부서번호를 각 각 묶어주면 소계를 따로 묶어서 출력할 수 있다

 

또 한, SELECT 문에서는 모든 데이터가 RESULT SET이 일어나고 그 값으로 PARTITION으로 분류한다

MAX(점수), AVG(점수)등을 이용하고 OVER (PARTITION BY 이름)으로 묶는다면 개인별 최고 점수가 출력된다

쉽게말해 구분마다 GROUP BY 하여 컬럼에 값을 담는다라고 생각하면된다

ROLLUP과 CUBE 설명은 다음에 다시 하겟다

 

 

CUME_DIST - 관련 DATSET안에서 해당 ROW의 위치를 0에서 1까지의 값으로 표시 해준다.

 

PERCENT_RANK - 순위가 0에서 1까지의 값으로 지정되지만 소수점도 같이 지정된다

 

NTILE(N) - N이라는 숫자를 지정하면 그 숫자만큼 순위를 지정할 수 있다

                      예로 10명의 사원에서 N을 2로 지정했다면 1 다섯개와 2 다섯 개가 지정된다

 

ROW_NUMBER() - PARTITION 내의 ROW들에 순서대로 UNIQUE한 일련번호를 부여한다

 

 

728x90
반응형

'IT_Web > Oracle' 카테고리의 다른 글

Oracle DECODE 활용법  (3) 2020.02.27
Oracle WINDOW 함수 활용법  (0) 2020.02.27
Oracle 시퀀스, DDL 및 서브쿼리 활용문제  (0) 2020.02.27
Oracle 테이블 생성 및 제약조건  (0) 2020.02.26
Oracle 시퀀스 개념과 활용  (0) 2020.02.26
728x90
반응형

학습 목표

– 시퀀스 활용과 DDL 활용방법을 숙지한다

단 서브쿼리의 숙지를 위해 서브쿼리만 사용하도록하자

그리고 DCL의 숙지를 위해 테이블을 추가 수정 삭제 시 오류 문으로 인해 잘못된 정보를 저장하지

않도록 테이블 추가 삭제 수정시 SELECT문을 활용하여 사전 데이터를 확인하여 작업하자

그리고 ROLLBACK과 COMMIT을 활용하여 잘못된 정보 저장을 방지하자

 

 

DDL 문제 -

테이블을 구조와 정보를 복사하는 방법

 

1. EMP 테이블과 같은 EMP_TEMP 테이블 생성하시오

CREATE TABLE EMP_TEMP AS SELECT * FROM EMP;

 

2. DEPT 테이블과 같은 DEPT_TEMP 테이블을 생성하시오

CREATE TABLE DEPT_TEMP AS SELECT * FROM DEPT;

 

3. SALGRADE 테이블과 같은 SALGRADE_TEMP 테이블을 생성하시오

CREATE TABLE SALGRADE_TEMP AS SELECT * FROM SALGRADE;

 

4. 교육생의 TRAINEES 테이블을 만드시오

IDX(숫자 4자리이상), NAME(문자형 5자리이상), TEL(문자형 13자리이상),

CLASS (문자형 10자리이상) ROOM(숫자 3자리이상), INDATE(날짜형),

GENDER(남자 또는 여자 둘 중 하나 지정)

 

아이디 넘버를 PRIMARY KEY로 설정하고 이름은 필수입력값으로 지정한다

제약조건은 필히 ALTER 사용

 

ALTER TABLE TRAINEES ADD CONSTRAINT TRAINEES_CK_GENDER CHECK (GENDER IN('남','여'));

 

5. 교육생을 추가하시오 ( 교육생 정보는 아래와 같다 )

일반방법으로 추가 한다  1, '이순신', '02-3333-5555', '자바개발자반', 401 2019-06-05, 남

 

INSERT INTO COUNTRIES(IDX, NAME, TEL, CLASS, ROOM, INDATE)

VALUES(1,'이순신', '02-3333-5555', '자바개발자반', 401 2019-06-05, 남);

 

두 번째는 ( 아이디 번호를 작성할 때 MAX 활용법과 시퀀스 두 가지 모두 사용하자 )(dual 활용방법도 생각할 수 있다)

2, '유관순', '010-9999-0231', '빅데이터반', 402, SYSDATE, 여

 

INSERT INTO TRAINEES(IDX, NAME, TEL, CLASS, ROOM, INDATE)

VALUES( (SELECT NVL(MAX(REGION_ID)+1,0)

              FROM TRAINEES), 

              '유관순', '010-9999-0231', '빅데이터반', 402, SYSDATE, 여);

 

CREATE SEQUENCE seq_trainees_idx

START WITH 2

INCREMENT BY 1

 

INSERT INTO TRAINEES VALUES(SEQ_TRAINEES_IDX.NEXTVAL,

                                                                    '유관순', '010-9999-0231', '빅데이터반', 402, SYSDATE, '여자')

 

 

6. 사내 확장으로 부서가 증가했다. ORACL, SQL, JAVA, JSP 각 순서대로 부서번호를 50, 60, 70, 80번을 부여하고 지역 또 한, BUSAN, ILSAN, INCHON, BUNDANG 추가하시오

 

INSERT INTO CHAP10HW_DEPT (DEPTNO, DNAME, LOC) VALUES (50, 'ORACLE', 'BUSAN');

INSERT INTO CHAP10HW_DEPT (DEPTNO, DNAME, LOC) VALUES (60, 'SQL', 'ILSAN');

INSERT INTO CHAP10HW_DEPT (DEPTNO, DNAME, LOC) VALUES (70, 'SELECT', 'INCHEON');

INSERT INTO CHAP10HW_DEPT (DEPTNO, DNAME, LOC) VALUES (80, 'DML', 'BUNDANG');

 

 

테이블 구조만 복사하는 방법

7. EMP 테이블의 구조만 같은 RETIRE 테이블을 새로 생성하시오

CREATE TABLE RETIRE AS SELECT * FROM EMP WHERE 1 <> 1;

 

 

8. EMP_TEMP 부서별 최대 급여를 받는 사원의 모든 정보를 RETIRE 테이블로 이동하시오

(EMP_TEMP 테이블을 호출하여 칼럼을 클릭하면 해당 칼럼 이름을 출력할 수 있다 활용할 것)

 

INSERT INTO RETIRE (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)

SELECT * FROM EMP_TEMP WHERE (DEPTNO, SAL) IN (SELECT DEPTNO, MAX(SAL)

                                                                        FROM EMP_TEMP

                                                                        GROUP BY DEPTNO)

 

 

9. 30번 부서가 매출 부진으로 인해 부서이동을 실시한다 30번 내에서 급여등급 2인 사원만 20번 부서로 이동하라

UPDATE EMP_TEMP SET DEPTNO = 20

WHERE ENAME IN ( SELECT ENAME

                           FROM EMP_TEMP E, SALGRADE S

                           WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL

                           AND DEPTNO = 30

                           AND S.GRADE = 2)

 

 

10. EMP_TEMP테이블에 8명의 신입사원을 추가하여라 (아래는 신입사원의 정보이다)

7201, 'TEST_USER1', 'MANAGER', 7788, 2016-01-02, 4500, NULL, 50

7202, 'TEST_USER2', 'CLERK', 7201, 2016-02-21 1800, NULL, 50

7203, 'TEST_USER3', 'ANALYST', 7201, 2016-04-11, 3400, NULL, 60

7204, 'TEST_USER4', 'SALESMAN', 7201, 2016-05-31, 2700, 300, 60

7205, 'TEST_USER5', 'CLERK', 7201, 2016-07-20, 2600, NULL, 70

7206, 'TEST_USER6', 'CLERK', 7201, 2016-09-08, 2600, NULL, 70

7207, 'TEST_USER7', 'LECTURER', 7201, 2016-10-28, 2300, NULL, 80

7208, 'TEST_USER8', 'STUDENT', 7201, 2018-03-09, 1200, NULL, 80

 

 

 

11. DEPT_TEMP 40번 부서기준으로 30번 부서와 통합하려한다 ( 이름과 지역을 동일시하자 )

UPDATE DEPT_TEMP SET (DNAME, LOC, deptno) = (SELECT DNAME, LOC, deptno

                                                                     FROM DEPT_TEMP

                                                                     WHERE DEPTNO = 30)

WHERE DEPTNO = 40;

 

그리고 EMP_TEMP 테이블과 DEPT_TEMP테이블의 변경된 정보를 확인하여라

 

 

12. EMP_TEMP에 속한 사원 중 50번 부서에서 근무하는 사원들의 평균 급여보다 많은 급여를 받고 있는 사원들을70번 부서로 옮기는 SQL문을 작성하세요

UPDATE EMP_TEMP SET DEPTNO = 70

WHERE SAL > (SELECT AVG(SAL)

                     FROM EMP

                     WHERE DEPTNO = 50);

 

 

 

13. EMP_TEMP에 속한 사원중, 60번 부서의 사원중에 입사일이 가장 빠른 사원보다

늦게 입사한 사원의 급여를 10% 인상하고 80번 부서로 옮기는 SQL문을 작성하시오

 

UPDATE EMP_TEMP SET SAL = SAL*1.1, DEPTNO = 80

WHERE HIREDATE > (SELECT MIN(HIREDATE)

                             FROM EMP_TEMP

                             WHERE DEPTNO = 60);

 

 

 

 

14. EMP_TEMP에 속한 사원 중, 급여 등급이 5인 사원을 삭제하는 SQL문을 작성하세요

DELETE FROM EMP_TEMP

WHERE EMPNO IN (SELECT E.EMPNO

                           FROM EMP_TEMP E, SALGRADE_TEMP S

                           WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL

                           AND S.GRADE = 5);

 

 

 

15. EMP_TEMP에서 부서별 제일 오래 근무한 사원을 찾으세요.

SELECT ename FROM EMP_TEMP

WHERE (hiredate, deptno) IN (SELECT min(hiredate), deptno

                                        FROM EMP_TEMP

                                         GROUP BY deptno)

 

 

 

16. 각 부서의 급여 최소가 900이상 최대가 10000이하인 부서의 사원들 중 1500이상의 급여를 받는

사원들의 평균 급여액을 출력하라

SELECT avg(sal) FROM emp

WHERE sal >= 1500

GROUP BY deptno

HAVING min(sal) >= 900 AND max(sal) <= 10000;

 

 

17. 급여 등급이 4등급인 사원들의 사원번호, 이름, 급여, 근무 부서이름, 근무지역을 가져온다.

SELECT e.empno

FROM emp e, detp d, salgrade s

WHERE e.deptno = d.deptno AND E.SAL BETWEEN S.LOSAL AND S.HISAL

AND S.GRADE = 4

 

 

 

18. SMITH 사원의 직속상관과 동일한 직무를 가지고 있는 사원들의 사원번호, 이름, 직무를 가져온다.

e1 : SMITH의 정보

e2 : SMITH의 직속상관 정보

e3 : 직속상관과 동일한 직무를 가지고 있는 사원들의 정보

 

SELECT empno, ename, job FROM EMP

WHERE job = (SELECT job

                    FROM EMP

                     WHERE empno = (SELECT mgr

                                               FROM EMP

                                               WHERE ename='SMITH')

                     )

 

SELECT e3.empno, e3.ename, e3.job FROM EMP e1, EMP e2, EMP e3

WHERE e1.mgr = e2.empno AND e2.job = e3.job

AND e1.ename = 'SMITH';

 

728x90
반응형

'IT_Web > Oracle' 카테고리의 다른 글

Oracle WINDOW 함수 활용법  (0) 2020.02.27
Oracle 분석함수 활용법  (0) 2020.02.27
Oracle 테이블 생성 및 제약조건  (0) 2020.02.26
Oracle 시퀀스 개념과 활용  (0) 2020.02.26
Oracle DB인덱스 종류 및 개념  (0) 2020.02.26
728x90
반응형

Spring Boot의 특징

  • 임베디드 톰캣(Embed Tomcat), 제티, 언더토우를 사용하여 독립 실행이 가능한 스프링 애플리케이션 개발
  • 통합 스타터를 제공하여 메이븐/그레이들 구성 간소화
  • 번거로운 XML 설정을 요구하지 않음
  • JAR을 사용하여 자바 옵션만으로도 배포가능
  • 애플리케이션의 모니터링과 관리를 위한 스프링 액츄에이터(Spring Actuator)제공

Stater 내부의 의존성 확인 방법

  1.  Spring Boot Reference Guide를 참고하여 확인할 수 있다 (링크를 참조하자)https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#using-boot-starter
 

Spring Boot Reference Documentation

This section goes into more detail about how you should use Spring Boot. It covers topics such as build systems, auto-configuration, and how to run your applications. We also cover some Spring Boot best practices. Although there is nothing particularly spe

docs.spring.io

 

stater 내부의 의존성을 확인하는 이유는 다음과 같습니다

  • 특정 스타터를 사용하려하는데 의존 관계가 궁금할 때
  • 의존관계를 확인하지 않고 Spring-boot-starter를 추가했는데 의존관계 설정이 궁금할 때 

Spring-boot-starter는 다음 여섯 가지 의존성을 제공한다

  1. spring-boot : 스프링 부트에서 기본 제공하는 의존성
  2. spring-boot-autoconfigure : 스프링 부트의 자동 환경 구성에 필요한 의존성
  3. spring-boot-starter-logging : 각종 로그를 사용하는데 필요한 의존성
  4. javax.annotation-api : 소프트웨어의 결함을 탐지하는 어노테이션을 지원하는 의존성
  5. spring-core : 스프링 코어를 사용하는데 필요한 의존성
  6. snakeyaml : yaml을 사용하는 데 필요한 의존성

애플리케이션 스타터

  • spring-boot-starter : 스프링 부트 코어, auto-configuration, logging yaml 제공
  • spring-boot-starter-aop : 관전 지향 프로그래밍을 위한 스타터
  • spring-boot-starter-batch : 스프링 배치를 사용하는데 필요한 스타터
  • spring-boot-starter-data-jpa : 스프링 데이터 JPA와 하이버네이트를 사용하는데 필요한 스타터
  • spring-boot-starter-data-redis : 메모리 저장방식의 저장소인 레디스와 자바에서 쉽게 레디스를 사용하게끔 도와주는 제디스 설정 자동화 스타터
  • spring-boot-starter-data-rest : 스프링 데이터 저장소 방식에 맞춘 REST API를 제공하는데 사용하는 스타터
  • spring-boot-starter-thymeleaf : 타임리프 템플릿 엔진을 사용하는 데 필요한 스타터
  • spring-boot-starter-jdbc : 톰캣 JDBC 커넥션풀에 사용하는 스타터
  • spring-boot-starter-security : 각종 보안에 사용하는 스프링 시큐리티 스타터
  • spring-boot-starter-oauth2 : OAuth2 인증에 사용하는 스타터
  • spring-boot-starter-validation : 자바 빈 검증(Java Bean Vaildation)에 사용하는 스타터
  • spring-boot-starter-web : 웹을 만드는 데 사용하는 스타터(스프링MVC, REST형, 임베디드 톰캣, 기타 라이브러리 포함)

 

728x90
반응형

+ Recent posts

Powered by Tistory, Designed by wallel