2008-08-23
2-29 External Table
OS> mkdir c:\EXT_TEST
####staff.txt#####
301,KWON,29,F,740205,2598659,107
302,KIM,30,M,730715,1824451,108
303,JUNG,22,F,810922,2411057,107
304,YUN,25,F,781102,2804478,109
305,PARK,24,M,790130,1496300,108
306,LEE,32,M,711013,1695521,110
307,KAWK,34,7108100,1135620,110
SQL> show user
USER is "HR"
SQL> CREATE OR REPLACE DIRECTORY extdir AS 'C:\EXT_TEST\';
CREATE OR REPLACE DIRECTORY extdir AS 'C:\EXT_TEST\'
*
ERROR at line 1:
ORA-01031: insufficient privileges <--Error
SQL> conn system/oracle
SQL> GRANT CREATE ANY DIRECTORY, DROP ANY DIRECTORY TO hr ;
SQL> CREATE OR REPLACE DIRECTORY extdir AS 'C:\EXT_TEST';
SQL> grant read, write on directory extdir to public ;
SQL> CREATE TABLE staff_ext (
sno NUMBER, sname VARCHAR2(10), age NUMBER, gender CHAR(2),
jumin1 CHAR(6), jumin2 CHAR(7), dno NUMBER)
ORGANIZATION EXTERNAL (
TYPE ORACLE_LOADER
DEFAULT DIRECTORY extdir
ACCESS PARAMETERS (
RECORDS DELIMITED BY NEWLINE
BADFILE 'staff_bad'
LOGFILE 'staff_log'
FIELDS TERMINATED BY ',' (
sno char, sname CHAR,
age char, gender CHAR,
jumin1 char, jumin2 CHAR,
dno char ) )
LOCATION ('staff.txt') )
PARALLEL 5
REJECT LIMIT 200 ;
SQL> select * from staff_ext ;
SNO SNAME AGE GE JUMIN1 JUMIN2 DNO
---------- ---------- ---------- -- ------ ------- ----------
301 KWON 29 F 740205 2598659 107
302 KIM 30 M 730715 1824451 108
303 JUNG 22 F 810922 2411057 107
304 YUN 25 F 781102 2804478 109
305 PARK 24 M 790130 1496300 108
306 LEE 32 M 711013 1695521 110
-- 원본 staff.txt에서 에러난 리인을 수정.
SQL> select * from staff_ext ;
SNO SNAME AGE GE JUMIN1 JUMIN2 DNO
---------- ---------- ---------- -- ------ ------- ----------
301 KWON 29 F 740205 2598659 107
302 KIM 30 M 730715 1824451 108
303 JUNG 22 F 810922 2411057 107
304 YUN 25 F 781102 2804478 109
305 PARK 24 M 790130 1496300 108
306 LEE 32 M 711013 1695521 110
307 KAWK 34 M 708100 2135620 110
7 rows selected.
SQL> desc staff_ext ;
Name Null? Type
----------------------------------------- -------- ----------------------------
SNO NUMBER
SNAME VARCHAR2(10)
AGE NUMBER
GENDER CHAR(2)
JUMIN1 CHAR(6)
JUMIN2 CHAR(7)
DNO NUMBER
SQL> select length(sname) from staff_ext ;
교재 2-35 와 비교
SQL> select length(sname) from staff_ext ;
LENGTH(SNAME)
-------------
4
4
4
4
4
4
4
SQL> select length(sname) from staff_ext ;
LENGTH(SNAME)
-------------
4
3
4
4
4
4
4
7 rows selected.
SQL> select * from staff_ext
where sname = 'YUN' ;
no rows selected
SQL> select * from staff_ext
where sname = 'YUN ' ;
SNO SNAME AGE GE JUMIN1 JUMIN2 DNO
---------- ---------- ---------- -- ------ ------- ----------
304 YUN 25 F 781102 2804478 109
================================================================================
#############
## 7th Day ##
#############
## Chapter 03 ##
3-12
CREATE TABLE hr.emps
(e_id NUMBER(4)
,name VARCHAR2(4) CONSTRAINT nn_name_emps NOT NULL
,address VARCHAR2(30) DEFAULT '서울'
,salary NUMBER(8)
,jumin VARCHAR2(13) NOT NULL
,deptid NUMBER(4)
,CONSTRAINT pk_e_id_emps PRIMARY KEY(e_id)
,CONSTRAINT uk_jumin_emps UNIQUE(jumin)
,CONSTRAINT ck_salary_emps CHECK(salary > 0)
,CONSTRAINT fk_emps_departments FOREIGN KEY(deptid)
REFERENCES hr.departments(department_id) ON DELETE SET NULL
);
3-15 ~ 3-26
1. UNCONDITIONAL INSERT ALL
CREATE TABLE sal_history
(EMPID number(6), HIREDATE date, SAL number);
CREATE TABLE mgr_history
(EMPID number(6), MGR NUMBER(6), SAL number);
INSERT ALL
INTO sal_history (EMPID, HIREDATE,SAL)
VALUES (employee_id, hire_date, salary)
INTO mgr_history (EMPID, MGR, SAL)
VALUES (employee_id, manager_id, salary)
SELECT employee_id, hire_date, salary, manager_id
FROM employees
WHERE employee_id >200;
SELECT employee_id , hire_date , salary , manager_id
FROM employees
WHERE employee_id > 200;
EMPLOYEE_ID HIRE_DAT SALARY MANAGER_ID
----------- -------- ---------- ----------
201 96/02/17 13000 100
202 97/08/17 6000 201
203 94/06/07 6500 101
204 94/06/07 10000 101
205 94/06/07 12000 101
206 94/06/07 8300 205
(결과)
select * from sal_history;
EMPID HIREDATE SAL
---------- -------- ----------
201 96/02/17 13000
202 97/08/17 6000
203 94/06/07 6500
204 94/06/07 10000
205 94/06/07 12000
206 94/06/07 8300
SELECT * FROM mgr_history;
EMPID MGR SAL
---------- ---------- ----------
201 100 13000
202 201 6000
203 101 6500
204 101 10000
205 101 12000
206 205 8300
rollback ;
--------------------------------------------------------------------------------
2. CONDITIONAL INSERT ALL
rollback ;
CREATE TABLE else_table
AS
SELECT employee_id EMPID, hire_date HIREDATE
,salary SAL, manager_id MGR
FROM hr.employees
WHERE 1=2 ;
DELETE FROM hr.employees
WHERE employee_id = 900 ;
INSERT INTO hr.employees
VALUES (900, '','신상현','ks7009','',sysdate,'AC_MGR',
30000,'',205,110);
commit ;
SELECT employee_id, hire_date, salary, manager_id
FROM employees
WHERE employee_id > 200;
EMPLOYEE_ID HIRE_DAT SALARY MANAGER_ID
----------- -------- ---------- ----------
201 96/02/17 13000 100
202 97/08/17 6000 201
203 94/06/07 6500 101
204 94/06/07 10000 101
205 94/06/07 12000 101
206 94/06/07 8300 205
900 07/07/13 30000 205
INSERT ALL
WHEN salary > 10000
THEN INTO sal_history (EMPID, HIREDATE, SAL)
VALUES (employee_id, hire_date, salary)
WHEN manager_id > 200
THEN INTO mgr_history(EMPID, MGR, SAL)
VALUES (employee_id, manager_id, salary)
ELSE INTO else_table(EMPID, HIREDATE, SAL, MGR)
VALUES (employee_id, hire_date,salary,manager_id)
SELECT employee_id, hire_date, salary, manager_id
FROM employees
WHERE employee_id > 200;
(결과)
SELECT * FROM sal_history;
EMPID HIREDATE SAL
---------- -------- ----------
201 96/02/17 13000
205 94/06/07 12000
900 04/02/20 30000
SELECT * FROM mgr_history;
EMPID MGR SAL
---------- ---------- ----------
202 201 6000
206 205 8300
900 205 30000
SELECT * FROM else_table ;
EMPID HIREDATE SAL MGR
---------- -------- ---------- ----------
203 94/06/07 6500 101
204 94/06/07 10000 101
rollback ;
--------------------------------------------------------------------------------
3. Conditional FIRST INSERT
rollback ;
SELECT employee_id, hire_date, salary, manager_id
FROM employees
WHERE employee_id > 200;
EMPLOYEE_ID HIRE_DAT SALARY MANAGER_ID
----------- -------- ---------- ----------
201 96/02/17 13000 100
202 97/08/17 6000 201
203 94/06/07 6500 101
204 94/06/07 10000 101
205 94/06/07 12000 101
206 94/06/07 8300 205
900 07/07/13 30000 205
INSERT first
WHEN salary > 10000
THEN INTO sal_history (EMPID, HIREDATE, SAL)
VALUES (employee_id, hire_date, salary)
WHEN manager_id > 200
THEN INTO mgr_history(EMPID, MGR, SAL)
VALUES (employee_id, manager_id, salary)
ELSE INTO else_table(EMPID, HIREDATE, SAL, MGR)
VALUES (employee_id, hire_date,salary,manager_id)
SELECT employee_id, hire_date, salary, manager_id
FROM employees
WHERE employee_id > 200;
(교재 실습)
CREATE TABLE special_sal (DEPTID NUMBER(6), SAL NUMBER(8,2));
CREATE TABLE hiredate_history_00 (DEPTID NUMBER(6), HIREDATE DATE);
CREATE TABLE hiredate_history_99 (DEPTID NUMBER(6), HIREDATE DATE);
CREATE TABLE hiredate_history (DEPTID NUMBER(6), HIREDATE DATE);
SELECT department_id DEPTID, SUM(salary) SAL, MAX(hire_date) HIREDATE
FROM employees
GROUP BY department_id;
DEPTID SAL HIREDATE
---------- ---------- --------
10 4400 87/09/17
20 19000 97/08/17
30 24900 99/08/10
40 6500 94/06/07
50 156400 00/03/08
60 28800 99/02/07
70 10000 94/06/07
80 304500 00/04/21
90 58000 93/01/13
100 51600 99/12/07
110 50300 04/02/20
7000 99/05/24
INSERT FIRST
WHEN SUM_SAL > 25000
THEN INTO special_sal
VALUES(department_id, SUM_SAL)
WHEN MAXHIREDATE like ('%00%')
THEN INTO hiredate_history_00
VALUES (department_id, MAXHIREDATE)
WHEN MAXHIREDATE like ('%99%')
THEN INTO hiredate_history_99
VALUES (department_id, MAXHIREDATE)
ELSE INTO hiredate_history
VALUES (department_id, MAXHIREDATE)
SELECT department_id, SUM(salary) SUM_SAL
,MAX(hire_date) MAXHIREDATE
FROM employees
GROUP BY department_id;
SELECT * FROM special_sal;
DEPTID SAL
---------- ----------
50 156400
60 28800
80 304500
90 58000
100 51600
110 50300
SELECT * FROM hiredate_history_00;
SELECT * FROM hiredate_history_99;
DEPTID HIREDATE
---------- --------
30 99/08/10
99/05/24
SELECT * FROM hiredate_history;
DEPTID HIREDATE
---------- --------
10 87/09/17
20 97/08/17
40 94/06/07
70 94/06/07
--------------------------------------------------------------------------------
4. PIVOT 실습
1. 준비
1) NON-RELATIONAL (비정규화된 테이블) Table 생성
CREATE TABLE sales_qty_week
(WEEK_ID NUMBER(2)
,employee_id number(2)
,prod_cd varchar2(10)
,MON_qty NUMBER(6)
,TUE_qty NUMBER(6)
,WED_qty NUMBER(6)
,THU_qty NUMBER(6)
,FRI_qty NUMBER(7)
,CONSTRAINT pk_sales_qty_week PRIMARY KEY (week_id, employee_id, prod_cd)
)TABLESPACE example ;
SQL> desc hr.sales_qty_week
이름 널? 유형
----------------------------------------- -------- ---------------
WEEK_ID NOT NULL NUMBER(2)
EMPLOYEE_ID NOT NULL NUMBER(2)
PROD_CD NOT NULL VARCHAR2(10)
MON_QTY NUMBER(6)
TUE_QTY NUMBER(6)
WED_QTY NUMBER(6)
THU_QTY NUMBER(6)
FRI_QTY NUMBER(7)
2) 행입력
INSERT INTO sales_qty_week
(week_id, employee_id, prod_cd,
MON_qty, TUE_qty,WED_qty,THU_qty,FRI_qty)
VALUES (1, 10, 'A', 10, 5, 6, 10, 3) ;
INSERT INTO sales_qty_week
(week_id, employee_id, prod_cd,
MON_qty, TUE_qty,WED_qty,THU_qty,FRI_qty)
VALUES (1, 10, 'B', 1, 2, 3, 4, 5) ;
INSERT INTO sales_qty_week
(week_id, employee_id, prod_cd,
MON_qty, TUE_qty,WED_qty,THU_qty,FRI_qty)
VALUES (1, 20, 'A', 5, 5, 5, 5, 5) ;
col MON_QTY format 999
col TUE_QTY format 999
col WED_QTY format 999
col THU_QTY format 999
col FRI_QTY format 999
col PROD_CD format a2
col PROD_ID format a2
col week_id format 999
col employee_id format 999
SELECT * FROM sales_qty_week ;
WEEK_ID EMPLOYEE_ID PR MON_QTY TUE_QTY WED_QTY THU_QTY FRI_QTY
------- ----------- -- ------- ------- ------- ------- -------
1 10 A 10 5 6 10 3
1 10 B 1 2 3 4 5
1 20 A 5 5 5 5 5
지금까지 만든 NON-RELATIONAL TABLE의 데이터를 RELATIONAL TABLE에
입력해봅시다.
2. RELATIONAL TABLE 생성
CREATE TABLE sale_qty_week_re
(week_id NUMBER(2)
,EMPLOYEE_ID NUMBER(2)
,PROD_ID VARCHAR2(2)
,wd_cd NUMBER(1)
,qty number(6)
)
TABLESPACE example ;
1 월 2 화 3 수 4목 5금
desc sale_qty_week_re
이름 널? 유형
----------------------------------------- -------- ----------------------------
WEEK_ID NUMBER(2)
EMPLOYEE_ID NUMBER(2)
PROD_ID VARCHAR2(2)
WD_CD NUMBER(1)
QTY NUMBER(6)
(참고)
desc sales_qty_week
이름 널? 유형
----------------------------------------- -------- ----------------------------
EMPLOYEE_ID NOT NULL NUMBER(2)
PROD_CD NOT NULL VARCHAR2(10)
MON_QTY NUMBER(6)
TUE_QTY NUMBER(6)
WED_QTY NUMBER(6)
THU_QTY NUMBER(6)
FRI_QTY NUMBER(7)
WEEK_ID NOT NULL NUMBER(2)
3. NON-RELATIONAL TABLE(sales_qty_week)의 데이터를
RELATIONAL TABLE(sale_qty_week_re)에 입력
INSERT ALL
INTO sale_qty_week_re(week_id, employee_id,prod_id, wd_cd, qty)
VALUES(week_id, employee_id, prod_cd,1,MON_qty)
INTO sale_qty_week_re(week_id, employee_id,prod_id, wd_cd, qty)
VALUES(week_id, employee_id, prod_cd,2,TUE_qty)
INTO sale_qty_week_re(week_id, employee_id,prod_id, wd_cd, qty)
VALUES(week_id, employee_id, prod_cd,3,WED_qty)
INTO sale_qty_week_re(week_id, employee_id,prod_id, wd_cd, qty)
VALUES(week_id, employee_id, prod_cd,4,THU_qty)
INTO sale_qty_week_re(week_id, employee_id,prod_id, wd_cd, qty)
VALUES(week_id, employee_id, prod_cd,5,FRI_qty)
SELECT EMPLOYEE_ID,PROD_CD,MON_QTY,TUE_QTY,WED_QTY,THU_QTY
,FRI_QTY,WEEK_ID
FROM sales_qty_week ;
(확인)
SELECT * FROM sale_qty_week_re;
WEEK_ID EMPLOYEE_ID PR WD_CD QTY
------- ----------- -- ---------- ----------
1 10 A 1 10
1 10 B 1 1
1 20 A 1 5
1 10 A 2 5
1 10 B 2 2
1 20 A 2 5
1 10 A 3 6
1 10 B 3 3
1 20 A 3 5
1 10 A 4 10
1 10 B 4 4
1 20 A 4 5
1 10 A 5 3
1 10 B 5 5
1 20 A 5 5
15 개의 행이 선택되었습니다.
--4. 기존 NON-relational table export 받고 drop ;
OS> exp system/oracle tables=hr.sales_qty_week file=c:\oracle\dump.dmp
SQL> drop table sales_qty_week purge;
--5. table rename
SQL> alter table sale_qty_week_re rename to sales_qty_week ;
6. 입력된 데이터 확인 후, RELATIONAL TABLE에 PK 추가
ALTER TABLE sales_qty_week
ADD CONSTRAINT pk_sale_qty_week
PRIMARY KEY (week_id, employee_id, prod_id,wd_cd) ;
SELECT *
FROM sales_qty_week
ORDER BY week_id,employee_id, prod_id,wd_cd;
WEEK_ID EMPLOYEE_ID PR WD_CD QTY
------- ----------- -- ---------- ----------
1 10 A 1 10
1 10 A 2 5
1 10 A 3 6
1 10 A 4 10
1 10 A 5 3
1 10 B 1 1
1 10 B 2 2
1 10 B 3 3
1 10 B 4 4
1 10 B 5 5
1 20 A 1 5
1 20 A 2 5
1 20 A 3 5
1 20 A 4 5
1 20 A 5 5
15 개의 행이 선택되었습니다.
SQL>
--------------------------------------------------------------------------------
3-27
MERGE 구문 실습
용어
목적테이블 : 삽입 및 갱신이 일어나는 테이블
사용테이블 : USING 절에 기술되는 테이블
(주의)
1. 삽입 및 갱신되는 컬럼들, 특히 ON 절에 기술되는 컬럼은 동일한 DataType 이어야 합니다.
2. ON 절에 기술된 기준이 되는 컬럼의 데이터는 UPDATE SET 시킬 수 없습니다.
MERGE 구문 시 다음 사항을 확인하시기 바랍니다.
1. 목적테이블과 대상 테이블이 꼭 같을 필요는 없습니다.
2. 삽입 및 갱신되는 컬럼들, 특히 ON 절에 기술되는 컬럼은 반드시 동일한 DataType 이어야 합니다.
3. 컬럼 이름이 동일할 필요는 없습니다.
4. UPDATE와 INSERT 부분에 기술되는 컬럼갯수들이 목적테이블과 사용테이블 어느 쪽과 같을 필요는 없습니다.
5. ON 절에 기술된 기준이 되는 컬럼의 데이터는 UPDATE SET 부분에 명시하면 않됩니다.
-------------------------------------------------------------------------------------------------------
목적 테이블과 사용테이블은 DataType은 동일하고 컬럼갯수 및 컬럼 이름이 다릅니다.
MERGE 시에 갱신은 한개 컬럼, 삽입은 3개 등 목적 테이블과 사용테이블의 일부 컬럼만을 가지고 실습합니다.
CREATE TABLE copy_emp01
(EMPNO NUMBER(6),
ENAME VARCHAR2(20),
JOB VARCHAR2(10) DEFAULT 'NO JOB',
MGR NUMBER(6),
HIREDATE DATE,
SAL NUMBER(8,2),
COMM NUMBER(2,2),
DEPTNO NUMBER(4)
);
--copy_emp01 테이블에 데이터가 없어요..
10g only
MERGE INTO copy_emp01 c
USING employees e
ON (c.empno = e.employee_id)
WHEN NOT MATCHED THEN
INSERT (c.empno,c.ename,c.hiredate)
VALUES(e.employee_id, e.FIRST_NAME, sysdate);
## WHEN NOT MATCHED THEN 이하만 적었읍니다.
10g 에서는 정상수행, 9i 에서는 Error !!
9i, 10g
MERGE INTO copy_emp01 c
USING employees e
ON (c.empno = e.employee_id)
WHEN MATCHED THEN
UPDATE SET
c.deptno = e.department_id
WHEN NOT MATCHED THEN
INSERT (c.empno,c.ename,c.hiredate)
VALUES(e.employee_id, e.FIRST_NAME, sysdate);
107 행이 병합되었습니다. <--INSERT만 됨
SQL> SELECT empno, ename, hiredate, JOB, deptno FROM copy_emp01;
(empno, ename, hiredate(sysdate 함수처리 결과), Job(DEFAULT 값인 NO JOB) 컬럼에만 값이 입력됨)
(DEPTNO 컬럼은 널값)
10g only
MERGE INTO copy_emp01 c
USING employees e
ON (c.empno = e.employee_id)
WHEN MATCHED THEN
UPDATE SET
c.deptno = e.department_id ;
9i or 10g
MERGE INTO copy_emp01 c
USING employees e
ON (c.empno = e.employee_id)
WHEN MATCHED THEN
UPDATE SET
c.deptno = e.department_id
WHEN NOT MATCHED THEN
INSERT (c.empno,c.ename,c.hiredate)
VALUES(e.employee_id, e.FIRST_NAME, sysdate); <--함수가 사용되었네요
SQL> SELECT empno, ename, hiredate, JOB, deptno FROM copy_emp01;
(DEPTNO 컬럼값이 employees 테이블의 DEPARTMENT_ID 값으로 갱신됨)
--------------------------------------------------------------------------------
3-31
### Flashback Version Query 연습 ###
c:\oracle>sqlplus hr/hr
drop table hr.emps13_01 purge ;
create table hr.emps13_01(empno, ename, sal, deptno)
as
select employee_id, last_name, salary, department_id
from hr.employees
where department_id in (10,20,90) ;
col ename format a15
SELECT * FROM hr.emps13_01 order by 1;
Update hr.emps13_01 SET ename='관우' WHERE empno=101 ;
commit ;
Update hr.emps13_01 SET sal=0 WHERE empno=101 ;
commit ;
delete from hr.emps13_01 where empno=101 ;
commit ;
SELECT ename,SAL
,versions_startscn ST_SCN
,versions_endscn END_SCN
,versions_XID TX_ID
,versions_operation OPERATION
FROM hr.emps13_01
VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE
WHERE empno=101;
ENAME SAL ST_SCN END_SCN TX_ID O
--------------- ---------- ---------- ---------- ---------------- -
관우 17000 1002189 01001200E0010000 D
관우 17000 1002179 1002189 0A000700E6010000 U
Kochhar 17000 1002179
================================================================================
## Chapter 04 ##
4-13
(Query 1)
SELECT department_id, job_id, avg(salary) AS avgsal
FROM employees
GROUP BY department_id,job_id ;
(Query 2)
SELECT job_id, manager_id,avg(salary)
FROM employees
GROUP BY job_id,manager_id ;
이 두 쿼리의 결과를 한번에 실행하고 싶다면, . . .
(방법 1)
SELECT department_id, job_id, null AS manager_id, avg(salary) AS avgsal
FROM employees
GROUP BY department_id,job_id
UNION ALL
SELECT null , job_id, manager_id,avg(salary)
FROM employees
GROUP BY job_id,manager_id ;
(9i 버젼 이후)
SELECT department_id, job_id, manager_id,avg(salary)
FROM employees
GROUP BY GROUPING SETS ((department_id,job_id), (job_id,manager_id));
--------------------------------------------------------------------------------
4-8 세션2개를 연다
(세션1)
SELECT department_id, job_id, salary
FROM employees
WHERE department_id < 60
ORDER BY 1,2 ;
(세션2)
SELECT department_id, job_id, SUM(salary)
FROM employees
WHERE department_id < 60
GROUP BY ROLLUP(department_id, job_id);
(세션3)
--(Query1)
SELECT department_id, job_id, SUM(salary)
FROM employees
WHERE department_id < 60
GROUP BY (department_id, job_id);
--(Query2)
SELECT department_id, SUM(salary)
FROM employees
WHERE department_id < 60
GROUP BY department_id;
--(Query3)
SELECT SUM(salary)
FROM employees
WHERE department_id < 60
GROUP BY ();
Query 1,2,3을 UNION ALL 처리 함.
이를 간단히 표시하면, GROUP BY rollup (A,B,C) 는 다음과 같은 결과를 보인다.
GROUP BY (A,B,C)
UNION ALL
GROUP BY (A,B,null)
UNION ALL
GROUP BY (A, null, null)
UNION ALL
GROUP BY (null, null, null)
이를 간단히 표시하면, GROUP BY CUBE (A,B,C) 는 다음과 같은 결과를 보인다.
GROUP BY (A,B,C)
UNION ALL
GROUP BY (A,B,null)
UNION ALL
GROUP BY (A, null, null)
UNION ALL
GROUP BY (null, null, null)
UNION ALL
GROUP BY (A,null,C)
UNION ALL
GROUP BY (null,B,C)
UNION ALL
GROUP BY (null,b, null)
UNION ALL
GROUP BY (null, null,c)
--------------------------------------------------------------------------------
4-10
Cube는 조합가능한 모든 그룹핑이 모두 처리됩니다.
SELECT department_id, job_id, SUM(salary),
FROM employees
WHERE department_id < 50
GROUP BY CUBE(department_id, job_id);
간단히 설명하면,
GROUP BY (department_id, job_id)
UNION ALL
GROUP BY (department_id, null)
UNION ALL
GROUP BY (null, null)
UNION ALL
GROUP BY (null, job_id)
--------------------------------------------------------------------------------
4-12
(교재 구문)
SELECT department_id DEPTID, job_id JOB, SUM(salary),
GROUPING(department_id) GRP_DEPT,
GROUPING(job_id) GRP_JOB
FROM employees
WHERE department_id < 50
GROUP BY ROLLUP(department_id, job_id);
SELECT department_id, job_id, SUM(salary),
GROUPING(department_id) GRP_DEPT,
GROUPING(job_id) GRP_JOB
FROM employees
GROUP BY ROLLUP(department_id, job_id);
SELECT department_id, job_id, SUM(salary),
GROUPING(department_id) GRP_DEPT,
GROUPING(job_id) GRP_JOB
FROM employees
GROUP BY CUBE(department_id, job_id);
--------------------------------------------------------------------------------
4-17 Composite Columns
GROUP BY rollup (A,B,C,D)
GROUP BY (A,B,C,D)
GROUP BY (A,B,C)
GROUP BY (A,B)
GROUP BY (A)
GROUP BY ()
GROUP BY rollup (A,(B,C,D))
GROUP BY (A,B,C,D)
GROUP BY (A)
GROUP BY ()
--------------------------------------------------------------------------------
4-18
GROUP BY GROUPING SETS ((a),(b),(c))
= GROUP BY GROUPING SETS (a,b,c)
GROUP BY GROUPING SETS ((a,b,c))
=== GROUP BY (a,b,c)
--------------------------------------------------------------------------------
4-19 Composite Columns
(설명 수정)
그림 (1) --> (2)
(설명 수정)
1. (department_id, job_id) <-- 요기 수정
2. (department_id, job_id, manager_id)
3. (department_id)
4 ()
group by ROLLUP( department_id,(job_id, manager_id));
group by department_id,job_id, manager_id
union all
group by department_id
union all
group by ()
group by ROLLUP( department_id,job_id, manager_id);
group by department_id,job_id, manager_id
union all
group by department_id,job_id
union all
group by department_id
union all
group by ()
SELECT department_id, job_id, manager_id,SUM(salary)
,GROUPING(department_id) GRP_DEPT
,GROUPING(job_id) GRP_JOB
,GROUPING(manager_id) GRP_MGR
FROM employees
GROUP BY ROLLUP( department_id,(job_id, manager_id));
group by department_id,job_id, manager_id 2
group by department_id 3
group by () 4
--------------------------------------------------------------------------------
4-22 Concatenated Groupings
(기준)
1. 모든 그룹핑 형식이 한번씩 고려되야함.
2. 중복된 필드는 한번으로 처리
3. () (Grand Total Group)는 삭제
(내용)
GROUP BY A, rollbup (A,C), cube (C,D) 결과
A A,C C,D A A,C C,D ACD
A C A A,C C AC
() D A A,C D AD A
() A A,C
select department_id, job_id, manager_id, sum(salary)
,GROUPING(department_id) GRP_DEPT
,GROUPING(job_id) GRP_JOB
,GROUPING(manager_id) GRP_MGR
from hr.employees
GROUP BY department_id, ROLLUP(job_id), CUBE(manager_id);
department_id job_id (manager_id)
() ()
(department_id,job_id,manager_id)
(department_id,job_id,)
(department_id,,manager_id)
(department_id,)
--------------------------------------------------------------------------------
4-21
GROUP BY GROUPING SETS((a), (b)), GROUPING SETS((c), (d))
GROUP BY GROUPING SETS(a, b), GROUPING SETS(c, d)
(a) (c)
(b) (d)
GROUPING SETS((a,c),(a,d),(b,c),(b,d))
--------------------------------------------------------------------------------
##########################
## ROLLUP_CUBE_보충연습 ##
##########################
## 아래의 예제는 스스로 관련 테이블을 만들고, 데이터도 입력한 다음에
실습해 보시기 바랍니다.
## 아래는 이런 정보를 조회할 수 있구나 라는 느낌을 가져 보시라고
표시한 것입니다.
스스로 분석해 보세요.. 재미있습니다.
1.대리점별 판매건수
select store_name , count(*)
from month_sales
group by store_name ;
2.대리점별 월별 판매건수
select store_name , to_char(sale_date,'MM') MON , count(*)
from month_sales
group by store_name , to_char(sale_date,'MM') ;
3.대리점별 월별 판매건수
select store_name ,
sum(decode (to_char(sale_date,'MM'),10 ,1,0)) "10월" ,
sum(decode (to_char(sale_date,'MM'),11 ,1,0)) "11월" ,
sum(decode (to_char(sale_date,'MM'),12 ,1,0)) "12월"
from month_sales
group by store_name , to_char(sale_date,'MM') ;
select store_name ,
sum(decode (to_char(sale_date,'MM'),10 ,1,0)) "10월" ,
sum(decode (to_char(sale_date,'MM'),11 ,1,0)) "11월" ,
sum(decode (to_char(sale_date,'MM'),12 ,1,0)) "12월"
from month_sales
group by store_name ;
4.대리점별 월별 판매총액
select store_name ,
sum(decode (to_char(sale_date,'MM'),10 ,sale_price,0)) "10월" ,
sum(decode (to_char(sale_date,'MM'),11 ,sale_price,0)) "11월" ,
sum(decode (to_char(sale_date,'MM'),12 ,sale_price,0)) "12월"
from month_sales
group by store_name , to_char(sale_date,'MM') ;
select store_name ,
sum(decode (to_char(sale_date,'MM'),10 ,sale_price,0)) "10월" ,
sum(decode (to_char(sale_date,'MM'),11 ,sale_price,0)) "11월" ,
sum(decode (to_char(sale_date,'MM'),12 ,sale_price,0)) "12월"
from month_sales
group by cube(store_name) ;
select nvl(store_name,'Total') ,
sum(decode (to_char(sale_date,'MM'),10 ,sale_price,0)) "10월" ,
sum(decode (to_char(sale_date,'MM'),11 ,sale_price,0)) "11월" ,
sum(decode (to_char(sale_date,'MM'),12 ,sale_price,0)) "12월" ,
sum(sale_price) "TOTAL"
from month_sales
group by cube(store_name) ;
4.대리점별 월별 판매총액
select nvl(str_nm,'Total') , sum(decode(mon,10,total,0)) "10월" ,
sum(decode(mon,11,total,0)) "11월",
sum(decode(mon,12,total,0)) "12월",
sum(decode(mon,10,total,0)) + sum(decode(mon,11,total,0)) +
sum(decode(mon,12,total,0)) "TOTAL"
from ( select store_name str_nm, extract (month from sale_date ) mon , sum(sale_price) total
from month_sales
group by cube(store_name , extract (month from sale_date ) ) )
group by str_nm ;
================================================================================
#############
## 8th Day ##
#############
## Chapter 05 ##
5-6
SELECT parameter, value FROM nls_session_parameters ;
ALTER SESSION SET nls_date_format='YYYY-MM-DD HH24:MI:SS' ;
ALTER SESSION SET nls_timestamp_format='YYYY-MM-DD HH24:MI:SSXFF' ;
ALTER SESSION SET nls_timestamp_tz_format='YYYY-MM-DD HH24:MI:SSXFF TZR' ;
ALTER SESSION SET time_zone='+1:00' ;
set linesize 200
col sysdate format a19
col current_date format a19
col current_timestamp format a33
col localtimestamp format a26
col sessiontimezone format a6
col dbtimezone format a6
SELECT sysdate, current_date, current_timestamp, localtimestamp
,sessiontimezone, dbtimezone
FROM dual ;
SYSDATE CURRENT_DATE CURRENT_TIMESTAMP LOCALTIMESTAMP SESSIO DBTIME
------------------- ------------------- --------------------------------- -------------------------- ------ ------
2007-11-14 15:34:27 2007-11-14 07:34:27 2007-11-14 07:34:27.342000 +01:00 2007-11-14 07:34:27.342000 +01:00 +00:00
SQL> ALTER SESSION SET time_zone='+4:00' ;
sysdate
SQL> SELECT sysdate, current_date, current_timestamp, localtimestamp
,sessiontimezone, dbtimezone
FROM dual ;
SYSDATE CURRENT_DATE CURRENT_TIMESTAMP LOCALTIMESTAMP SESSIO DBTIME
------------------- ------------------- --------------------------------- -------------------------- ------ ------
2007-11-14 15:35:23 2007-11-14 10:35:23 2007-11-14 10:35:23.122000 +04:00 2007-11-14 10:35:23.122000 +04:00 +00:00
--------------------------------------------------------------------------------
5-9
참고) database의 time_zone 변경방법
c:\> sqlplus sys/oracle as sysdba
SQL> alter database set time_zone='+9:00' ;
alter database set time_zone='+9:00'
*
ERROR at line 1:
ORA-30079: cannot alter database timezone when database has TIMESTAMP WITH
LOCAL TIME ZONE columns
1행에 오류:
ORA-30079: 데이터베이스에 TIMESTAMP WITH LOCAL TIME ZONE 열이 있는 경우
데이터베이스 시간대를 변경할 수 없음
col owner format a10
col table_name format a15
col column_name format a20
SQL> select owner, table_name, column_name
from dba_tab_columns
where data_type like 'TIMESTAMP% WITH LOCAL TIME ZONE';
OWNER TABLE_NAME COLUMN_NAME
---------- --------------- --------------------
OE ORDERS ORDER_DATE
HR TIMETEST T_TSLTZ
2. export 툴을 이용해서 위의 두 table을 export 함
OS> exp system/oracle tables=(oe.orders, hr.timetest) file=c:\oracle\dump1.dmp direct=y
3. table drop
(10g)
- recyclebin에 drop 된 테이블 정보가 남기때문에
- drop 시 purge 옵션을 사용하든가
purge dba_recyclebin 명령어를 이용해서 휴지통 정보도 같이 삭제.
(9i)
- drop 만 하면됨
(~8i)
- TIMESTAMP WITH LOCAL TIME ZONE 데이터형식이 없음
SQL> drop table oe.orders cascade constraints PURGE;
SQL> drop table hr.timetest cascade constraints purge;
SQL> alter database set time_zone='+9:00' ;
alter database set time_zone='+9:00'
*
ERROR at line 1:
ORA-30079: cannot alter database timezone when database has TIMESTAMP WITH
LOCAL TIME ZONE columns
SQL> select original_name from dba_recyclebin ;
ORIGINAL_NAME
--------------------------------
ORD_SALES_REP_IX
ORD_CUSTOMER_IX
ORD_ORDER_DATE_IX
ORDER_PK
ORDERS
A1
SQL> purge dba_recyclebin ;
SQL> select original_name from dba_recyclebin ;
no rows selected
4. 설정 변경
SQL> alter database set time_zone='+9:00' ;
Database altered.
5. db 재 가동
SQL> conn sys/oracle as sysdba
SQL> shutdown immediate
SQL> startup
6. exported tables을 import
OS> imp system/oracle tables=timetest fromuser=hr touser=hr file=c:\oracle\dump1.dmp
OS> imp system/oracle tables=orders fromuser=oe touser=oe file=c:\oracle\dump1.dmp
--------------------------------------------------------------------------------
5-18 INTERVAL Data Type의 활용
준비과정1) 테이블 생성
drop table hr.test_interval purge ;
CREATE TABLE hr.test_interval
(t_id NUMBER(3)
,iytm INTERVAL YEAR(3) TO MONTH
,idts INTERVAL DAY(3) TO SECOND(2) );
준비과정2) 자료입력
INSERT INTO hr.test_interval VALUES (1, INTERVAL '123-2' YEAR(3) TO MONTH
,INTERVAL '4 5:12:10.21' DAY(3) TO SECOND (2)) ;
INSERT INTO hr.test_interval VALUES (2, INTERVAL '200' MONTH
,INTERVAL '4' DAY (3)) ; <--16년8개월
INSERT INTO hr.test_interval VALUES (3, INTERVAL '99' YEAR
, INTERVAL '5:12:10.22' HOUR TO SECOND(2)) ;
INSERT INTO hr.test_interval VALUES (4, INTERVAL '99' YEAR
, INTERVAL '10:30' HOUR TO MINUTE) ;
INSERT INTO hr.test_interval VALUES (5, INTERVAL '99' YEAR
, INTERVAL '240' HOUR ) ;
INSERT INTO hr.test_interval(t_id, idts)
VALUES (6, INTERVAL '18' DAY(2));
INSERT INTO hr.test_interval VALUES (7, INTERVAL '123-2' YEAR(3) TO MONTH
, INTERVAL '5 5:12' DAY TO MINUTE);
INSERT INTO hr.test_interval VALUES (8, INTERVAL '123' YEAR(3)
,INTERVAL '400' DAY(3) ) ;
INSERT INTO hr.test_interval VALUES (9, INTERVAL '123' MONTH
,INTERVAL '400' HOUR ) ;
INSERT INTO hr.test_interval VALUES (10, INTERVAL '123' MONTH
,INTERVAL '400' MINUTE ) ;
INSERT INTO hr.test_interval VALUES (11, INTERVAL '123-30' YEAR(3) MONTH
,INTERVAL '400' MINUTE ) ;
INSERT INTO hr.test_interval VALUES (12, INTERVAL '123-30' YEAR(3) MONTH
*
ERROR at line 1:
ORA-01867: the interval is invalid
INSERT INTO hr.test_interval VALUES (12, INTERVAL '123-11' YEAR(3) TO MONTH
,INTERVAL '30:400' HOUR TO MINUTE );
,INTERVAL '30:400' HOUR TO MINUTE )
*
ERROR at line 2:
ORA-01851: minutes must be between 0 and 59
INSERT INTO hr.test_interval VALUES (12, INTERVAL '123-11' YEAR(3) TO MONTH
,INTERVAL '30:59' HOUR TO MINUTE );
INSERT INTO hr.test_interval VALUES (13, '123-11'
,'400 10:10:10.22');
준비과정3) 입력자료 확인
SQL> col t_id format 999
SQL> col iytm format a10
SQL> col idts format a20
SQL>
SQL> SELECT * FROM test_interval;
## 기간 데이터형식의 활용
SQL> SELECT sysdate + IYTM, sysdate + IDTS FROM test_interval;
--------------------------------------------------------------------------------
5-25
EXTRACT : 날짜 데이터에서 형식요소에 해당하는 값을 추출해서
숫자값을 반환합니다.
SQL> SELECT sysdate, EXTRACT (YEAR FROM SYSDATE) "연도" FROM dual ;
SYSDATE 연도
-------- ----------
07/11/14 2007
SQL> SELECT sysdate, EXTRACT (YEAR FROM SYSDATE)+3000 "연도" FROM dual ;
SYSDATE 연도
------------------- ----------
08/01/18 5008
SQL> SELECT sysdate, EXTRACT (YEAR FROM SYSDATE) FROM dual ;
SYSDATE EXTRACT(YEARFROMSYSDATE)
-------- ------------------------
07/11/14 2007
SQL>
SQL> SELECT sysdate, EXTRACT (MONTH FROM SYSDATE) FROM dual ;
SYSDATE EXTRACT(MONTHFROMSYSDATE)
-------- -------------------------
07/11/14 11
SQL>
SQL> SELECT sysdate, EXTRACT (DAY FROM SYSDATE) FROM dual ;
SYSDATE EXTRACT(DAYFROMSYSDATE)
-------- -----------------------
07/11/14 14
SQL>
SQL> SELECT sysdate, EXTRACT (HOUR FROM SYSDATE) FROM dual ;
SELECT sysdate, EXTRACT (HOUR FROM SYSDATE) FROM dual
*
ERROR at line 1:
ORA-30076: invalid extract field for extract source
SQL> SELECT sysdate, EXTRACT (HOUR FROM CURRENT_DATE) FROM dual ;
SELECT sysdate, EXTRACT (HOUR FROM CURRENT_DATE) FROM dual
*
ERROR at line 1:
ORA-30076: invalid extract field for extract source
SQL> SELECT sysdate, EXTRACT (HOUR FROM CURRENT_TIMESTAMP)
,EXTRACT (HOUR FROM LOCALTIMESTAMP) FROM dual ;
SYSDATE EXTRACT(HOURFROMCURRENT_TIMESTAMP) EXTRACT(HOURFROMLOCALTIMESTAMP)
-------- ---------------------------------- -------------------------------
07/11/14 2 11
SQL>
SQL> ALTER SESSION SET nls_date_format='YYYY-MM-DD HH24:MI:SS' ;
SQL> ALTER SESSION SET nls_timestamp_format='YYYY-MM-DD HH24:MI:SSXFF' ;
SQL> ALTER SESSION SET nls_timestamp_tz_format='YYYY-MM-DD HH24:MI:SSXFF TZR' ;
SQL> SELECT sysdate, EXTRACT (HOUR FROM CURRENT_TIMESTAMP),
EXTRACT (HOUR FROM LOCALTIMESTAMP)
FROM dual ;
SYSDATE EXTRACT(HOURFROMCURRENT_TIMESTAMP)
------------------- ----------------------------------
EXTRACT(HOURFROMLOCALTIMESTAMP)
-------------------------------
2007-11-14 11:12:49 2
11
SQL> SELECT EXTRACT (HOUR FROM (TO_TIMESTAMP_TZ
('2007-11-14 10:00:00 +9:00'
,'YYYY-MM-DD HH24:MI:SS TZR')
)
) AS "HOUR"
FROM dual ;
HOUR
----------
1
SQL> SELECT sysdate, EXTRACT (MINUTE FROM CURRENT_TIMESTAMP),
EXTRACT (MINUTE FROM LOCALTIMESTAMP)
FROM dual ;
SYSDATE EXTRACT(MINUTEFROMCURRENT_TIMESTAMP)
------------------- ------------------------------------
EXTRACT(MINUTEFROMLOCALTIMESTAMP)
---------------------------------
2007-11-14 11:13:32 13
13
SQL> SELECT sysdate, EXTRACT (SECOND FROM CURRENT_TIMESTAMP),
EXTRACT (SECOND FROM LOCALTIMESTAMP)
FROM dual ;
SYSDATE EXTRACT(SECONDFROMCURRENT_TIMESTAMP)
------------------- ------------------------------------
EXTRACT(SECONDFROMLOCALTIMESTAMP)
---------------------------------
2007-11-14 11:13:47 47.433
47.433
SQL> SELECT sysdate, EXTRACT (TIMEZONE_HOUR FROM CURRENT_TIMESTAMP),
EXTRACT (TIMEZONE_HOUR FROM LOCALTIMESTAMP)
FROM dual ;
EXTRACT (TIMEZONE_HOUR FROM LOCALTIMESTAMP)
*
ERROR at line 2:
ORA-30076: invalid extract field for extract source
SQL> SELECT sysdate, EXTRACT (TIMEZONE_HOUR FROM CURRENT_TIMESTAMP)
FROM dual ;
SYSDATE EXTRACT(TIMEZONE_HOURFROMCURRENT_TIMESTAMP)
------------------- -------------------------------------------
2007-11-14 11:14:50 9
SQL> SELECT sysdate, EXTRACT (TIMEZONE_REGION FROM CURRENT_TIMESTAMP)
FROM dual ;
SYSDATE
-------------------
EXTRACT(TIMEZONE_REGIONFROMCURRENT_TIMESTAMP)
----------------------------------------------------------------
2007-11-14 11:15:44
UNKNOWN
SELECT EXTRACT(TIMEZONE_REGION FROM FROM_TZ(TIMESTAMP '2000-03-28 08:00:00'
,'Australia/North')
)
FROM DUAL ;
select
extract ( hour from interval '4 5:12:10.222' day to second(3) ) 시,
extract ( minute from interval '4 5:12' day to minute ) 분
from dual;
SQL> create table a (a1 interval year(3) to month);
SQL> insert into a values ('100-10');
SQL> insert into a values ('10-10');
SQL> insert into a values ('10-1');
SQL> select * from a;
A1
----------------------
+100-10
+010-10
+010-01
SQL> select extract(year from a1) from a;
EXTRACT(YEARFROMA1)
-------------------
100
10
10
SQL> select extract(month from a1) from a;
EXTRACT(MONTHFROMA1)
--------------------
10
10
1
--------------------------------------------------------------------------------
5-26
SELECT distinct tzname FROM v$timezone_names
ORDER BY 1 ;
--------------------------------------------------------------------------------
5-28
SQL> SELECT FROM_TZ (timestamp '2007-11-14 09:00:00.222', '+3:00') from dual ;
FROM_TZ(TIMESTAMP'2007-11-1409:00:00.222','+3:00')
---------------------------------------------------------------------------
2007-11-14 09:00:00.222000000 +03:00
SQL> SELECT FROM_TZ (timestamp '2007-11-14 09:00:00.222', 'ASIA/SEOUL') from dual ;
FROM_TZ(TIMESTAMP'2007-11-1409:00:00.222','ASIA/SEOUL')
---------------------------------------------------------------------------
2007-11-14 09:00:00.222000000 ASIA/SEOUL
SQL> SELECT FROM_TZ (timestamp '2007-11-14 09:00:00.222', 'ASI/SEOUL') from dual ;
SELECT FROM_TZ (timestamp '2007-11-14 09:00:00.222', 'ASI/SEOUL') from dual
*
ERROR at line 1:
ORA-01882: timezone region not found
--------------------------------------------------------------------------------
5-29
SQL> conn hr/hr
create table a1
(test1 timestamp with time zone
,test2 timestamp
) ;
insert into a1 values ('2000-12-01 11:00:00 +9:00'
, '2000-12-01 11:00:00') ;
insert into a1 values ('01-DEC-07 11:00:00 +9:00'
, '01-DEC-07 11:00:00') ;
col test1 format a33
col test2 format a30
select * from a1 ;
TEST1 TEST2
--------------------------------- ------------------------------
2000-12-01 11:00:00.000000 +09:00 2000-12-01 11:00:00.000000
0001-12-07 11:00:00.000000 +09:00 0001-12-07 11:00:00.000000 <--허억 년도랑 날이 ????
insert into a1
values (TO_TIMESTAMP_TZ('01-DEC-07 11:00:00 +9:00'
,'DD-MON-RR HH24:MI:SS TZR')
,TO_TIMESTAMP('01-DEC-07 11:00:00','DD-MON-RR HH24:MI:SS')
) ;
select * from a1 ;
TEST1 TEST2
--------------------------------- ------------------------------
2000-12-01 11:00:00.000000 +09:00 2000-12-01 11:00:00.000000
0001-12-07 11:00:00.000000 +09:00 0001-12-07 11:00:00.000000
2007-12-01 11:00:00.000000 +09:00 2007-12-01 11:00:00.000000
--> 처리된 것은 제대로 입력됩니다.
--------------------------------------------------------------------------------
5-30
conn hr/hr
ALTER SESSION SET nls_date_format='YYYY-MM-DD HH24:MI:SS' ;
ALTER SESSION SET nls_timestamp_format='YYYY-MM-DD HH24:MI:SSXFF' ;
ALTER SESSION SET nls_timestamp_tz_format='YYYY-MM-DD HH24:MI:SSXFF TZR' ;
SELECT sysdate, sysdate+TO_YMINTERVAL('1-0') from dual ;
SELECT sysdate, sysdate+TO_YMINTERVAL('0-9') from dual ;
SELECT sysdate, sysdate+TO_YMINTERVAL('1-1') from dual ;
--------------------------------------------------------------------------------
5-31
SELECT sysdate, sysdate+TO_DSINTERVAL('1 00:00:00.00') from dual ;
SELECT sysdate, sysdate+TO_DSINTERVAL('0 01:00:00.00') from dual ;
SELECT sysdate, sysdate+TO_DSINTERVAL('0 00:30:00.00') from dual ;
SELECT sysdate, sysdate+TO_DSINTERVAL('0 00:0:10.00') from dual ;
SELECT sysdate, sysdate+TO_DSINTERVAL('1 00:30:10.00') from dual ;
SQL>
--------------------------------------------------------------------------------
================================================================================
## Chapter 06 ##
6-3
SQL> select last_name
from hr.employees
where (employee_id, department_id) =
(select employee_id, department_id
from hr.employees
where last_name = 'Abel') ;
LAST_NAME
---------------
Abel
SQL> select last_name
from hr.employees
where (employee_id, department_id) =
(select employee_id, department_id
from hr.employees
where last_name = 'King') ;
(select employee_id, department_id
*
ERROR at line 4:
ORA-01427: single-row subquery returns more than one row
--------------------------------------------------------------------------------
6-5
(Pairwise comparison)
SELECT employee_id, manager_id, department_id
FROM hr.employees
WHERE (manager_id, department_id) IN
(SELECT manager_id, department_id
FROM hr.employees
WHERE employee_id IN (174, 199) )
AND employee_id NOT IN (174,199)
order by 1,2 ;
EMPLOYEE_ID MANAGER_ID DEPARTMENT_ID
----------- ---------- -------------
174 149 80
199 124 50
manager_id = 149 and department_id = 80 또는
manager_id = 124 and department_id = 50
6-6
(Non-pairwise comparison)
SELECT employee_id, manager_id, department_id
FROM hr.employees
WHERE manager_id IN (SELECT manager_id
FROM hr.employees
WHERE employee_id IN (174, 199) )
and department_id IN (SELECT department_id
FROM hr.employees
WHERE employee_id IN (174, 199) )
AND employee_id NOT IN (174,199)
order by 1,2 ;
manager_id = 149 or manager_id = 124
department_id = 80 or department_id = 50
manager_id = 149 and department_id = 80 또는
manager_id = 149 and department_id = 50 또는
manager_id = 124 and department_id = 80 또는
manager_id = 124 and department_id = 50 또는
SQL> SELECT employee_id, manager_id, department_id
2 FROM hr.employees
3 WHERE employee_id IN (174, 199) ;
EMPLOYEE_ID MANAGER_ID DEPARTMENT_ID
----------- ---------- -------------
174 149 80
199 124 50
--------------------------------------------------------------------------------
6-8
SELECT e.employee_id, e.last_name, e.department_id, d.department_name
FROM employees e INNER JOIN departments d
ON (e.department_id = d.department_id)
ORDER BY (SELECT department_name
FROM departments d1
WHERE d1.department_id = e.department_id) ;
SELECT employee_id, last_name, department_id
FROM employees e
ORDER BY (SELECT department_name
FROM departments d
WHERE e.department_id = d.department_id) ;
--------------------------------------------------------------------------------
6-12
SELECT last_name, salary, department_id
FROM employees outer
WHERE salary > (SELECT AVG(salary)
FROM employees
WHERE department_id = outer.department_id)
ORDER BY 3,1 ;
SELECT last_name, salary, department_id
FROM hr.employees
ORDER BY 3, 1 ;
(INLINE VIEW)
select e.last_name, e.salary, e.department_id, a.DEPT_AVG
from employees e INNER JOIN
(SELECT department_id
,ROUND(avg(salary),0) as dept_avg
FROM employees
GROUP BY department_id) a
ON e.department_id = a.department_id
AND e.salary > a.dept_avg
order by 3,1;
--------------------------------------------------------------------------------
6-13
SELECT e.employee_id, last_name,e.job_id
FROM employees e
WHERE 2 <= (SELECT COUNT(*)
FROM job_history
WHERE employee_id = e.employee_id);
SELECT * FROM job_history order by 1 ;
--------------------------------------------------------------------------------
6-15
SELECT employee_id, last_name, job_id, manager_id
FROM employees outer
WHERE EXISTS ( SELECT 'X'
FROM employees
WHERE manager_id = outer.employee_id)
order by 1;
SELECT employee_id, last_name, job_id, manager_id
FROM employees outer
WHERE employee_id IN (SELECT distinct manager_id
FROM hr.employees )
order by 1 ;
(설명)
SELECT employee_id, last_name, job_id, department_id
from hr.employees
order by 1 ;
SELECT employee_id, last_name, manager_id
from hr.employees
order by 3 ;
SELECT employee_id, last_name, job_id, manager_id
FROM employees outer
WHERE NOT EXISTS ( SELECT 'X'
FROM employees
WHERE manager_id = outer.employee_id)
order by 1 ;
--------------------------------------------------------------------------------
6-17
create table emp16
as
select employee_id, last_name, salary, department_id
from hr.employees
order by 1 ;
alter table emp16
add (department_name varchar2(30)) ;
select * from emp16 ;
select department_id, department_name
from hr.departments ;
update hr.emp16 e16
set department_name = (SELECT department_name
FROM hr.departments
WHERE department_id = e16.department_id) ;
delete from emp16
where employee_id IN (select employee_id
FROM hr.emp_history ) ;
create table emp_history
as
select * from emp16
where department_id IN ( 80 , 50 ) ;
delete from emp16 a
where employee_id = (select employee_id from emp_history
where employee_id = a.employee_id) ;
--------------------------------------------------------------------------------
6-24
WITH
dept_costs AS (
SELECT d.department_name, SUM(e.salary) AS dept_total
FROM employees e, departments d
WHERE e.department_id = d.department_id
GROUP BY d.department_name),
avg_cost AS (
SELECT SUM(dept_total)/COUNT(*) AS dept_avg
FROM dept_costs)
SELECT *
FROM dept_costs
WHERE dept_total > (SELECT dept_avg FROM avg_cost)
ORDER BY department_name;
SELECT *
FROM ( SELECT d.department_name, SUM(e.salary) AS dept_total
FROM employees e, departments d
WHERE e.department_id = d.department_id
GROUP BY d.department_name)
WHERE dept_total > (SELECT dept_avg FROM (
(SELECT SUM(dept_total)/COUNT(*)
AS dept_avg
FROM (
SELECT d.department_name, SUM(e.salary) AS dept_total
FROM employees e, departments d
WHERE e.department_id = d.department_id
GROUP BY d.department_name)))
ORDER BY department_name;
================================================================================
#############
## 9th Day ##
#############
## Chapter 07 ##
7-11
SELECT LPAD(last_name, LENGTH(last_name)+(Level*4)-4, '-') AS org_chart
FROM employees
START WITH last_name = 'King'
CONNECT BY prior employee_id = manager_id;
King Level 1 4+4-4=4
Kochhar Level 2 7+8-4=7+4
LPAD(last_name, 40, '-')
--------------------------------------------------------------------------------
(문법설명)
SELECT LEVEL, employee_id, manager_id,
LPAD(last_name, LENGTH(last_name)+(Level*4)-4, '-') AS org_chart
FROM employees
START WITH last_name = 'King'
CONNECT BY PRIOR employee_id = manager_id;
START WITH last_name = 'King' <-- 시작하는 행을 명시하는 조건
CONNECT BY PRIOR employee_id = manager_id; <--방향
CONNECT BY employee_id = PRIOR manager_id
-->CONNECT BY PRIOR manager_id = employee_id
(참고)
SQL> select employee_id, last_name, manager_id
from hr.employees
order by 1 ;
--------------------------------------------------------------------------------
7-9
(교재)
SELECT Prior last_name, 'is commander of', last_name
FROM employees
START WITH manager_id is null
CONNECT BY prior employee_id = manager_id;
SELECT last_name, 'is commander of', Prior last_name
FROM employees
START WITH manager_id is null
CONNECT BY prior employee_id = manager_id;
SELECT employee_id, last_name, manager_id, PRIOR last_name
FROM employees
START WITH last_name = 'King'
CONNECT BY PRIOR employee_id = manager_id
ORDER BY 1 ;
(참고)
SQL> select employee_id, last_name, manager_id
from hr.employees
order by 1 ;
SELECT employee_id, last_name, manager_id, PRIOR last_name
FROM employees
START WITH last_name = 'King'
CONNECT BY PRIOR manager_id = employee_id
ORDER BY 1 desc;
--------------------------------------------------------------------------------
7-13
SELECT LPAD(last_name,
LENGTH(last_name)+(Level*4)-4, '-')
AS org_chart
FROM employees
START WITH last_name = 'Kochhar'
CONNECT BY prior employee_id = manager_id;
SELECT LPAD(last_name,
LENGTH(last_name)+(Level*4)-4, '-')
AS org_chart
FROM employees
WHERE last_name <> 'Higgins'
START WITH last_name = 'Kochhar'
CONNECT BY prior employee_id = manager_id;
SELECT LPAD(last_name,
LENGTH(last_name)+(Level*4)-4, '-')
AS org_chart
FROM employees
START WITH last_name = 'Kochhar'
CONNECT BY prior employee_id = manager_id
AND last_name <> 'Higgins';
================================================================================
##############
## 10th Day ##
##############
## Chapter 08 ##
8-9
SELECT first_name, last_name
FROM hr.employees
WHERE REGEXP_LIKE (first_name, '^Ste(v|ph)en$') ;
Steven
Stephen
8-10
SELECT street_address, REGEXP_INSTR(street_address,'[^[:alpha:]]') AS "RESULT"
FROM hr.locations
WHERE REGEXP_INSTR(street_address,'[^[:alpha:]]')>1 ;
[^[:alpha:]]
'^abc'
'^[abc]' '^(a|b|c)'
'^(abc)'
'^abc'
---------------------------------------------------------------------------
8-11
col Road format a50
set linesize 200
SELECT street_address,REGEXP_SUBSTR(street_address,' [^ ]+ ') AS "Road"
FROM locations ;
8-12
SQL> select regexp_replace (country_name, '(.)', '\1 ') "RESULT"
2 from hr.countries ;
-------------------------------------------------------------------
A r g e n t i n a
A u s t r a l i a
Argentina
Australia
select regexp_replace (country_name, '(..)', '\1 ') "RESULT"
from hr.countries ;
------------------
Ar ge nt in a
Au st ra li a
Argentina
Australia
select regexp_replace (country_name, '(.)', '\1 ') "RESULT"
from hr.countries ;
-----------------------------
A r g e n t i n a
A u s t r a l i a
Argentina
Australia
select regexp_replace (country_name, '(.)', '\1*') "RESULT"
from hr.countries ;
