yoni

오라클 본문

코딩

오라클

yoni-1117 2018. 7. 30. 15:39

show user;



show user;


grant select on departments to pmorauser; -- 이렇게하면 pmoruser에서도 departments테이블을 select해서 읽어올 수 있다.

grant select on employees to pmorauser;



select *

from dba_users; --관리자만 볼수있다. 그래서 오류


-- 현재 오라클 서버에 접속한 사용자(hr)가 만든 테이블명과 뷰명을 조회하는것


select * from tab;


/*

중요 !! 꼭 암기!!!

>>> select 문의 처리순서 <<<


5. select 컬럼명 -- select (고르다)

1. from 테이블명 

2. where 조건절 ---- where 절이 뜻하는 것은 해당 테이블에서 조건에 만족하는 행을 메모리(RAM)에 로딩(올리는것)하는 것이다.  

3. group by 절

4. having 그룹함수

6. order by 절


*/


select *

from employees; 


-- 현재 오라클 서버에 접속한 사용자(hr)가 만든 테이블명에 주석문을 단것을 조회하는 것.


--테이블 생성 이후에 해야할 일은 테이블명과 컬럼명에 주석문을 달아 두어야 한다.


select *

from user_tab_comments;

-- 현재 오라클 서버에 접속한 사용자(hr)가 만든 테이블명에 주석문을 단것을 조회하는 것.



create table tbl_member_test --tbl = 테이블

(id       varchar2(20)    -- 괄호 안은 바이트길이

,passwd varchar2(20)

,name varchar2(20)

,addr varchar2(100)

);



comment on table tbl_member_test  -- 주석(코멘트 달기)

is '회원정보 입력 임시 테이블z';



-- 현재 오라클 서버에 접속한 사용자(hr)가 만든 employees 테이블에 존재하는 컬럼에 주석문을 단것을 조회하는 것.

select column_name, comments 

from user_col_comments

where table_name='EMPLOYEES';


select column_name, comments 

from user_col_comments

where table_name='TBL_MEMBER_TEST'; -- 테이블name과 컬럼name 은 대문자!!


--컬럼에대한 주석문달기

comment on column tbl_member_test.id

is '회원 아이디';


comment on column tbl_member_test.passwd

is '회원 암호';


comment on column tbl_member_test.name

is '회원 이름';


comment on column tbl_member_test.addr

is '회원의 주소';


-- 데이터 추가하기

insert into tbl_member_test

values('superman','pclass','송성학','경기도 평택');


commit;


select*

from tbl_member_test --이 테이블에서 패스워드 값이 PCLASS =(같은) 행을 추출해라 라는거.

where passwd = 'PCLASS';


select*

from tbl_member_test --이 테이블에서 패스워드 값이 pclass =(같은) 행을 추출해라 라는거.  (대문자를 구분함)

where passwd = 'pclass';


select comments -- 커멘트만 보자는 말. 

from user_tab_comments

where table_name='EMPLOYEES';


--

describe employees;

--또는 

desc employees;

-- employees 테이블에 존재하는 컬럼명과 컬럼의 데이터 타입을 조회해 주는것.

-- NUMBER(8,2) = -999999.99 ~ 999999.99

-- NUMBER(6) = -999999 ~ 999999


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

--몽땅 다 . 보겠다.

select * --(보고자하는것)

from employees 

-- where(조건) 몽땅 다 올리니 조건이 필요없다. -- where 절이 뜻하는 것은 해당 테이블에서 조건에 만족하는 행을 메모리(RAM)에 로딩(올리는것)하는 것이다.  


--특정컬럼만볼때.

select employee_id, first_name, last_name, salary --특정값 설정 

from employees;


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

--컬럼(column) = Field = 열 = 속성 

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

--EMPLOYEE_ID    : 사원번호

--FIRST_NAME     : 성

--LAST_NAME      : 이름

--EMAIL          : 이메일

--PHONE_NUMBER   : 핸드폰번호

--HIRE_DATE      : 입사일자

--JOB_ID         : 직종아이디

--SALARY         : 기본급여

--COMMISSION_PCT : 수당퍼센티지

--MANAGER_ID     : 직속상관의 사원번호

--DEPARTMENT_ID  : 부서번호


-- 행(Row) = Record = 튜플(Tuple)

-- 한직원 한직원 행이 다모인것이 = 테이블.

-- employees = 테이블 = Entity(엔티티)


select *

from departments; -- 부서정보 테이블


select *

from locations; -- 지역정보 테이블


select * from tab; 


select *

from countries; -- 국가 정보 테이블


select *

from jobs; -- 직업 정보 테이블


desc departments;

--DEPARTMENT_ID     : 부서 번호

--DEPARTMENT_NAME   : 부서명

--MANAGER_ID        : 부서장의 사원번호

--LOCATION_ID       : 지역아이디     



--1. employees 테이블에서 부서번호가 50번인 사원들에 대해 사원번호,사원명,입사일자,기본급여를 나타내세요.

select employee_id, last_name, first_name, hire_date, salary --(보고자 하는것) 

from employees  --(테이블 에서~)

where Department_Id=50; --( 조건 (부서번호가 50번인 사원들)) -A



--2. employees 테이블에서 부서번호가 50번인 사원들에 대해 사원번호,사원명,입사일자,기본급여,직종번호,부서번호 를 나타내세요.

select employee_id, last_name, first_name, hire_date, salary ,--(보고자 하는것)

       job_id,department_id

from employees  --(테이블 에서~)

where Department_Id=50; --( 조건 (부서번호가 50번인 사원들)) -B


--[퀴즈] 위에 A와 B중에 CPU가 연산하는 시간이 적은 것은? 

 -- select이 적을수록 CPU연산이 작다 = 그러므로 A


--[퀴즈] 위에 A와 B중에 메모리(RAM)에 로드되어지는 크기가 작은것은? 

 -- A와 B는 같다.  모든것이 올라가는것이고 화면에 보이는것은 select절에 해당되는것만 뽑아서 모니터에 올라옴.






          ------------ ***** NULL 처리 ***** ------------

null 은 존재하지 않는 것이므로 사칙연산( + - * / )에 들어가면 그 결과는 무조건 null 이다. 


select 2+3 , 2+null, 3-null, 0*null, 1/null

from dual;


select employee_id,first_name,

        last_name, salary, commission_pct,

        salary * commission_pct,

        salary + (salary*commission_pct)

from employees;


------***** null을 처리해주는 함수*****------


1. nvl (numvalue)

2. nvl2


select nvl(7,3), -- null값이 없으면 앞에것을 나타냄. 

        nvl(null,3),  

        nvl('이순신','거북선'),

        nvl(null,'거북선')

from dual; 

-- null이라면 null이 아닌것을 나타냄.


select employee_id,first_name,

        last_name, salary, commission_pct,

        salary * commission_pct,

        salary + (salary*commission_pct),

        nvl(salary + (salary*commission_pct), salary) -- null인 사람들은 ,salary를 보여내어라 라는 뜻.

from employees;




select employee_id as "사원번호", --오라클에서 as 는 이퀄(같다)라는 말.

        first_name "성",           -- as는 생략가능하다.

        last_name 이름,            -- "" 를 생략가능

        salary "기본 급여",        -- 띄우고 싶을때는 ""를 사용해서 한다.

        commission_pct as 수당퍼센티지,

        nvl(salary + (salary*commission_pct), salary)  "월 급여" -- null인 사람들은 ,salary를 보여내어라 라는 뜻.

from employees;


--5/10-----------------------------------------------------------


select '자바 '||'오라클' -- ||이 문자열을 붙여준다.

from dual;



select employee_id as "사원번호",  

        first_name ||' '|| last_name as "사원명",   -- first와 last name을 붙였다. ||        

        salary "기본 급여",        

        commission_pct as 수당퍼센티지,

        nvl(salary + (salary*commission_pct), salary)  "월 급여"  

from employees;



select '오늘은 ' || sysdate || ' 입니다.' || 2*3 || '입니다.'  --문자든 숫자든 둘이 붙일 수 있다.

from dual;




-- nvl2 설명. 


select nvl2(7,3,2), --null이 아니라면 2번째값을 나타내주고 끝내줌.

        nvl2(null,3,2),  -- null이라면 3번째값을 나타내주고 끝냄.

        nvl2('이순신','거북선','난중일기'), -- null아니라 2번째값 나타냄

        nvl2(null,'거북선', '난중일기') -- null이라 3번째값 나타냄

from dual; 




select employee_id as "사원번호",  

        first_name ||' '|| last_name as "사원명",     

        salary "기본 급여",        

        commission_pct as 수당퍼센티지,

        nvl(salary + (salary*commission_pct), salary)  "월급1",

        nvl2(commission_pct, salary + (salary*commission_pct))

        from employees;

        

        

      desc employees; -- employees 에 저장된 컬럼이 뭔지 알아볼때.

      

----- 테이블에 컬럼 추가하기 (employees 테이블에 주민번호 컬럼을 추가해 보겠습니다.) 


alter table employees

add jubun varchar2(13)  -- 문자열로 생성하는이유. 숫자일경우 10이나 010 이나 같이보기 때문이다.

 

select 10+2 , 010+2  

from dual;


select 10, 010, '10' ,'010'

from dual;


select 0207304123456, '0207304123456'

from dual;

-- 제일앞에 0이 올수 있는 데이터라면 무조건 문자로 해야한다. 숫자로 하면 안된다.



desc employees -- 만든 jubun 컬럼 조회.

select * from employees



update employees set jubun = '5510151234567'

where employee_id = 100;


update employees set jubun = '8510151234567'

where employee_id = 101;


update employees set jubun = '6510152234567'

where employee_id = 102;


update employees set jubun = '7510151234567'

where employee_id = 103;


update employees set jubun = '5510152234567'

where employee_id = 104;


update employees set jubun = '6510151234567'

where employee_id = 105;


update employees set jubun = '5809201234567'

where employee_id = 106;


update employees set jubun = '0803153234567'

where employee_id = 107;


update employees set jubun = '0712154234567'

where employee_id = 108;


update employees set jubun = '8810151234567'

where employee_id = 109;


update employees set jubun = '8908152234567'

where employee_id = 110;


update employees set jubun = '9005052234567'

where employee_id = 111;


update employees set jubun = '6610151234567'

where employee_id = 112;


update employees set jubun = '6710151234567'

where employee_id = 113;


update employees set jubun = '6709152234567'

where employee_id = 114;


update employees set jubun = '5710151234567'

where employee_id = 115;


update employees set jubun = '5610151234567'

where employee_id = 116;


update employees set jubun = '5810152234567'

where employee_id = 117;


update employees set jubun = '7810151234567'

where employee_id = 118;


update employees set jubun = '7909151234567'

where employee_id = 119;


update employees set jubun = '7702152234567'

where employee_id = 120;


update employees set jubun = '7009151234567'

where employee_id = 121;


update employees set jubun = '7111011234567'

where employee_id = 122;


update employees set jubun = '8010131234567'

where employee_id = 123;


update employees set jubun = '8110191234567'

where employee_id = 124;


update employees set jubun = '9012132234567'

where employee_id = 125;


update employees set jubun = '9406251234567'

where employee_id = 126;


update employees set jubun = '9408252234567'

where employee_id = 127;


update employees set jubun = '9204152234567'

where employee_id = 128;


update employees set jubun = '8507251234567'

where employee_id = 129;


update employees set jubun = '6511111234567'

where employee_id = 130;


update employees set jubun = '0010153234567'

where employee_id = 131;


update employees set jubun = '0005254234567'

where employee_id = 132;


update employees set jubun = '0110194234567'

where employee_id = 133;


update employees set jubun = '0412154234567'

where employee_id = 134;


update employees set jubun = '0503253234567'

where employee_id = 135;


update employees set jubun = '9510012234567'

where employee_id = 136;


update employees set jubun = '9510021234567'

where employee_id = 137;


update employees set jubun = '9610041234567'

where employee_id = 138;


update employees set jubun = '9610052234567'

where employee_id = 139;


update employees set jubun = '7310011234567'

where employee_id = 140;


update employees set jubun = '7310092234567'

where employee_id = 141;


update employees set jubun = '7510121234567'

where employee_id = 142;


update employees set jubun = '7612012234567'

where employee_id = 143;


update employees set jubun = '7710061234567'

where employee_id = 144;


update employees set jubun = '7810052234567'

where employee_id = 145;


update employees set jubun = '6810251234567'

where employee_id = 146;


update employees set jubun = '6811062234567'

where employee_id = 147;


update employees set jubun = '6712052234567'

where employee_id = 148;


update employees set jubun = '5911251234567'

where employee_id = 149;


update employees set jubun = '5910062234567'

where employee_id = 150;


update employees set jubun = '6010191234567'

where employee_id = 151;


update employees set jubun = '5712062234567'

where employee_id = 152;


update employees set jubun = '5810231234567'

where employee_id = 153;


update employees set jubun = '6011051234567'

where employee_id = 154;


update employees set jubun = '6010182234567'

where employee_id = 155;


update employees set jubun = '6110191234567'

where employee_id = 156;


update employees set jubun = '6210112234567'

where employee_id = 157;


update employees set jubun = '6311132234567'

where employee_id = 158;


update employees set jubun = '8511112234567'

where employee_id = 159;


update employees set jubun = '8710131234567'

where employee_id = 160;


update employees set jubun = '8710072234567'

where employee_id = 161;


update employees set jubun = '9010171234567'

where employee_id = 162;


update employees set jubun = '9112072234567'

where employee_id = 163;


update employees set jubun = '9110241234567'

where employee_id = 164;


update employees set jubun = '9212251234567'

where employee_id = 165;


update employees set jubun = '9310232234567'

where employee_id = 166;


update employees set jubun = '9811151234567'

where employee_id = 167;


update employees set jubun = '9810252234567'

where employee_id = 168;


update employees set jubun = '9910301234567'

where employee_id = 169;


update employees set jubun = '0910153234567'

where employee_id = 170;


update employees set jubun = '1011153234567'

where employee_id = 171;


update employees set jubun = '1006153234567'

where employee_id = 172;


update employees set jubun = '1111154234567'

where employee_id = 173;


update employees set jubun = '1209103234567'

where employee_id = 174;


update employees set jubun = '1207154234567'

where employee_id = 175;


update employees set jubun = '0906153234567'

where employee_id = 176;


update employees set jubun = '0812113234567'

where employee_id = 177;


update employees set jubun = '9810132234567'

where employee_id = 178;


update employees set jubun = '8712111234567'

where employee_id = 179;


update employees set jubun = '8310012234567'

where employee_id = 180;


update employees set jubun = '6510191234567'

where employee_id = 181;


update employees set jubun = '6510221234567'

where employee_id = 182;


update employees set jubun = '6510232234567'

where employee_id = 183;


update employees set jubun = '8512131234567'

where employee_id = 184;


update employees set jubun = '8510182234567'

where employee_id = 185;


update employees set jubun = '7510192234567'

where employee_id = 186;


update employees set jubun = '8512192234567'

where employee_id = 187;


update employees set jubun = '9511151234567'

where employee_id = 188;


update employees set jubun = '7510192234567'

where employee_id = 189;


update employees set jubun = '8510161234567'

where employee_id = 190;


update employees set jubun = '9510192234567'

where employee_id = 191;


update employees set jubun = '0510133234567'

where employee_id = 192;


update employees set jubun = '0810194234567'

where employee_id = 193;


update employees set jubun = '0910183234567'

where employee_id = 194;


update employees set jubun = '1010134234567'

where employee_id = 195;


update employees set jubun = '9510032234567'

where employee_id = 196;


update employees set jubun = '9710181234567'

where employee_id = 197;


update employees set jubun = '9810162234567'

where employee_id = 198;


update employees set jubun = '7511171234567'

where employee_id = 199;


update employees set jubun = '7810172234567'

where employee_id = 200;


update employees set jubun = '7912172234567'

where employee_id = 201;


update employees set jubun = '8611192234567'

where employee_id = 202;


update employees set jubun = '7810252234567'

where employee_id = 203;


update employees set jubun = '7803251234567'

where employee_id = 204;


update employees set jubun = '7910232234567'

where employee_id = 205;


update employees set jubun = '8010172234567'

where employee_id = 206;


commit;


select * from employees


--[문제] employees 테이블에서 각 부서번호마다 존재하는 직종ID값을 출력하세요.

select department_id, job_id, first_name ||' ' || last_name

from employees;


select department_id, job_id -- 이름은 필요없음.  하지만 같은 직종들이 중복이됨..

from employees;


-- select 되어진 결과물에서 행의 결과값이 중복되어 나온다면 중복된 행을 제거하고 1개만 보이고 싶다.

--> select 다음에 distinct 을 사용하면 된다.

select distinct department_id, job_id

from employees;



-- select 되어진 결과물을 정렬(sort)하려면 order by절을 사용하면 된다.

select distinct department_id, job_id

from employees

order by department_id  asc; -- 오름차순 


select distinct department_id, job_id

from employees

order by department_id  desc;-- 내림차순


select distinct department_id, job_id

from employees

order by department_id; -- 오름차순 ( asc 를 안써줘도 자동으로 오름차순 )




  -------------------------*********** 비교 연산자 ***********--------------------------------------


-- [문제] employees 테이블에서 부서번호가 50번은 부서에 근무하는 사원들의

--  부서번호,사원번호,사원명,월급을 나타내세요.


select department_id as "부서번호", 

        employee_id as "사원번호",

        first_name || ' ' || last_name as "사원명",

        nvl2(commission_pct, salary+(salary*commission_pct), salary) as "월급"  

from employees

where department_id = 50



-- [문제] employees 테이블에서 부서번호가 50번이 아닌 부서에 근무하는 사원들의

--  부서번호,사원번호,사원명,월급을 나타내세요.


select department_id as "부서번호", employee_id as "사원번호" ,

        first_name || ' ' || last_name as "사원명",

        nvl2(commission_pct, salary+(salary*commission_pct), salary) as "월급"  

from employees

where department_id != 50 -- <> , != , ^=   3가지 모두 같지않다는말 1

--order by department_id;

--order by "부서번호";

order by 1; --1번째의 컬럼(부서번호세로줄)을 오름차순해라.




select department_id as "부서번호", employee_id as "사원번호" ,

        first_name || ' ' || last_name as "사원명",

        nvl2(commission_pct, salary+(salary*commission_pct), salary) as "월급"  

from employees

where department_id <> 50 -- <> , != , ^=   3가지 모두 같지않다는말 2

order by 1; 




select department_id as "부서번호", employee_id as "사원번호" ,

        first_name || ' ' || last_name as "사원명",

        nvl2(commission_pct, salary+(salary*commission_pct), salary) as "월급"  

from employees

where department_id ^= 50 -- <> , != , ^=   3가지 모두 같지않다는말 3

order by 1; 




select department_id as "부서번호", employee_id as "사원번호" ,

        first_name || ' ' || last_name as "사원명",

        nvl2(commission_pct, salary+(salary*commission_pct), salary) as "월급"  

from employees

where department_id < 50 -- 50번 미만 부서번호.

order by 1; 


select department_id as "부서번호", employee_id as "사원번호" ,

        first_name || ' ' || last_name as "사원명",

        nvl2(commission_pct, salary+(salary*commission_pct), salary) as "월급"  

from employees

where department_id >= 50 

order by 1; 



-- null은 존재하지 않는 것이므로 비교연산자( =, != , <>, ^=, >, <, >=, <= )를 사용할 수 없다. 대신에 is연산자를 사용한다.

-- employees 테이블에서 부서번호를 배정받지 못한 사원들을 출력하세요.

select * 

from employees

where department_id = null;  -- 안나옴.


select * 

from employees

where department_id is null; -- null은 비교연산자를 못쓰고 is연산자를 쓴다.



-- employees 테이블에서 부서번호를 배정받은 사원들을 출력하세요 ( null이 아닌사원 모두 출력.)

select * 

from employees

where department_id != null; -- 안됨.


select * 

from employees

where department_id is not null; -- is not 연산자를 사용. 




-- [문제] employees 테이블에서 부서번호가 50번이 아닌 부서에 근무하는 사원들의

--  부서번호,사원번호,사원명,월급을 나타내세요. ( null 까지 )


select department_id as "부서번호", employee_id as "사원번호" ,

        first_name || ' ' || last_name as "사원명",

        nvl2(commission_pct, salary+(salary*commission_pct), salary) as "월급"  

from employees

where nvl(department_id, -9999) != 50

order by 1;


select department_id, nvl(department_id,-9999), -- department_id의 값이 널이라면 -9999라 하겠다.  select 부분은 보여주고자 하는 부분을 나타내는것.

        first_name || ' ' || last_name

from employees



select department_id as "부서번호",

        nvl(department_id,-9999) as"부서번호2", -- department_id값이 null이라면 -9999라 한것을 보여주겠다는것 . select 부분은 보여주고자 하는 부분을 나타내는것.

        employee_id as "사원번호" ,

        first_name || ' ' || last_name as "사원명",

        nvl2(commission_pct, salary+(salary*commission_pct), salary) as "월급"  

from employees

where nvl(department_id, -9999) != 50

order by 1;







/*

  오라클은 테이블에 저장된 데이터값에 대해서만 대,소문자를 구분한다.

  employees 테이블에서 성(frist_name)이 'John' 인 사원만 

  사원번호, 사원명, 기본급여의 정보를 추출하세요.

*/


select employee_id,

        first_name || ' ' || last_name, 

        salary

from employees

where first_name = 'John';


select employee_id,

        first_name || ' ' || last_name, 

        salary

from employees

where first_name = 'john'; -- 데이터값에 대해 대소문자 구분되어서 안나옴.


select employee_id,

        first_name || ' ' || last_name, 

        salary

from employees

where first_name = 'JOHN'; -- 마찬가지로 데이터값에 대해 구분되어서 안나온다.


--그런데 나오고 싶다..

--- 문자열 함수중에 대,소문자를 변경해주는 것이 있다.

--1. upper : 모든 문자를 대문자로 변경해주는 함수.

--2. lower : 모든 문자를 소문자로 변경해주는 함수.

--3. initcap : 단어를 첫글자만 대문자로 나머지는 소문자로 변경해주는 함수.


select 'kOrEA seOUL',

        upper('kOrEA seOUL') ,

        lower('kOrEA seOUL') ,

        initcap('kOrEA seOUL')

from dual;




select employee_id,  -- 화면에 원래 값이 보임 .

        first_name,  

        first_name || ' ' || last_name, 

        salary

from employees

where lower(first_name) = lower('jOhN'); -- 전부가 같이 lower로 바꿔주면 검색이 가능하다. 화면에 보여줄때는 원래대로 나온다 select이 담당함.





----- [문제]  employees 테이블에서 성명을 'jOHn sEo' 로 검색을 하였을때 

------ 사원번호 , 성, 이름, 기본급여가 나와야한다.


select employee_id 사원번호,

        first_name 성,

        last_name 이름,

        salary 기본급여

from employees

where upper(first_name || ' ' || last_name) = upper('jOHn sEo'); --가운데 띄어쓰기 주의.






-----****** 연산자 or , and , not, in 연산자에 대해서 알아본다. ********-------------------

-- employees 테이블에서 부서번호가 30, 60, 90번 부서에 근무하는 사원들에 대해서 

-- 사원번호, 사원명, 연봉(월급 *12), 부서번호를 출력하세요.


SELECT employee_id,

        first_name || ' ' || last_name,

        nvl(salary+(salary*commission_pct), salary)*12 as "연봉", --null인 사람들은 ,salary를 보여내서 *12 = 연봉 이라는 뜻 (월급*12)

        department_id

from employees

where department_id = 30 or 

       department_id = 60 or

       department_id = 90; 



SELECT employee_id,

        first_name || ' ' || last_name,

        nvl(salary+(salary*commission_pct), salary)*12 as "연봉",   

        department_id

from employees

where department_id in(30,60,90); -- in 연산자 괄호 안은 or

-- 단 or는 in 보다 속도가 빠르므로 현업에서는 불편하더라도 or를 쓰자.


-- 연산자 or , and , not, in 

-- employees 테이블에서 부서번호가 30, 60, 90번이 아닌 부서에 근무하는 사원들에 대해서 

-- 사원번호, 사원명, 연봉(월급 *12), 부서번호를 출력하세요.


SELECT employee_id,

        first_name || ' ' || last_name,

        nvl(salary+(salary*commission_pct), salary)*12 as "연봉",   

        department_id

from employees

where department_id != 30 and  

       department_id != 60 and

       department_id != 90;


--or 은 한개라도 맞으면 맞는것

--and 는 모두 맞아야 맞는것.


SELECT employee_id,

        first_name || ' ' || last_name,

        nvl(salary+(salary*commission_pct), salary)*12 as "연봉",   

        department_id

from employees

where department_id not in(30,60,90); -- not in 은 괄호 안은 and


--null인 사람것도 구하기.

SELECT employee_id,

        first_name || ' ' || last_name,

        nvl(salary+(salary*commission_pct), salary)*12 as "연봉",   

        department_id

from employees

where nvl(department_id, -9999) not in(30,60,90);

--같은것.

SELECT employee_id,

        first_name || ' ' || last_name,

        nvl(salary+(salary*commission_pct), salary)*12 as "연봉",   

        department_id

from employees

where nvl(department_id,-9999) != 30 and  

       nvl(department_id,-9999) != 60 and

       nvl(department_id,-9999) != 90;




-- employees 테이블에서 부서번호가 30, 60, 90번 부서가 아닌 근무하는 사원들에 대해서 

-- 사원번호, 사원명, 연봉(월급 *12), 부서번호를 부서번호의 오름차순으로 정렬한 후, 연봉의 내림차순으로 출력하세요.


select employee_id as 사원번호,

        first_name || ' ' || last_name as 사원명,

        nvl(salary+(salary*commission_pct), salary)*12 as "연봉",   

        department_id as"부서번호"

from employees

where nvl(department_id,-9999) not in(30,60,90)

order by 4, 3 desc; --4번째(부서번호) 세로줄을 정렬하고 4번째줄(부서번호)을 기준으로 3번째(연봉)줄을 desc으로 정렬 (부서별로 연봉정렬) *  4뒤에는 asc이 생략되어도 오름차순정렬이됨.




-------**** and, or, not 연산자의 우선순위가 있다.********-------

select 2+3*4

from dual;



-- employees 테이블에서 부서번호가 30, 60, 90번 부서에 근무하는 사원들에 대해서 

-- 사원들중에 연봉이 30000 이상 50000 이하인 사원들만

-- 사원번호, 사원명, 연봉(월급 *12), 부서번호를 출력하세요.

SELECT employee_id as 사원번호,

        first_name || ' ' || last_name as 사원명,

        nvl(salary+(salary*commission_pct), salary)*12 as "연봉", 

        department_id as 부서번호

from employees

where department_id = 30 or 

       department_id = 60 or

       department_id = 90 and -- 부서번호가 30,60,90 인 사람들중에  

       nvl(salary+(salary*commission_pct), salary)*12 >=30000 and -- 연봉이 30000이상 50000이하인 사람들을 출력하는것. 하지만 우선순위가 and>or 이기때문에 and먼저 처리된다.

       nvl(salary+(salary*commission_pct), salary)*12 <=50000;

       -- 출력해보면 108000도 나온다.. 우선순위의 문제다. 

       -- and , or , not 연산자가 혼용되어지면 우선순위를 따르는데, 

       -- not > and > or 의 순위를 따라간다.

       

       -- 우선순위에 있어서 최우선은 "() 괄호" 이다.

       

select employee_id as 사원번호,

        first_name || ' ' || last_name as 사원명,

        nvl(salary+(salary*commission_pct), salary)*12 as "연봉", 

        department_id as 부서번호

from employees

where (department_id = 30 or 

       department_id = 60 or

       department_id = 90) and 

       nvl(salary+(salary*commission_pct), salary)*12 >=30000 and 

       nvl(salary+(salary*commission_pct), salary)*12 <=50000;

       --괄호를 통해서 우선순위를 정해준다.

       

SELECT employee_id as 사원번호,

        first_name || ' ' || last_name as 사원명,

        nvl(salary+(salary*commission_pct), salary)*12 as "연봉", 

        department_id as 부서번호

from employees

where department_id in(30,60,90)and

       nvl(salary+(salary*commission_pct), salary)*12 >=30000 and 

       nvl(salary+(salary*commission_pct), salary)*12 <=50000;

      --in 은 괄호가 이미 있는 or 이다.  

       



--범위를 나타내어주는 연산자가 있다. 

--그것은 A 부터 B까지 나타내어주는 것은 => between A and B

SELECT employee_id as 사원번호,

        first_name || ' ' || last_name as 사원명,

        nvl(salary+(salary*commission_pct), salary)*12 as "연봉", 

        department_id as 부서번호

from employees

where department_id in(30,60,90)and

       nvl(salary+(salary*commission_pct), salary)*12 between 30000 and 50000; -- between A이상 and B이하 (속도는 더 늦다.)

       

       

       

      -------****** like 연산자 ******--------- (~~처럼 , ~~같이 라는뜻)

select *

from employees

where department_id = 80;


select *

from employees

where department_id like 80; 

-- 위 두개는 똑같이 출력함. like 연산자는 = 의 의미이다. 별도의 특별한 의미가 있다.


update employees set first_name='J' -- 변경할 것.

where employee_id=100; --변경할 놈  

--데이터의 변경!


select *

from employees; --변경된거 확인 (메모리상(RAM)에서만)


rollback; -- 변경한 데이터를 취소하겠다.


select *

from employees; -- 롤백한거 확인.


update employees set first_name='J' -- 변경할 것.

where employee_id=100; --변경할 놈  

commit; -- 메모리상에서 변경되어진 것이 실제 디스크에 저장됨.


rollback; -- commit 한 이후에 롤백을 해도 복구가 안된다.


select *

from employees; -- commit 하면 롤백 불가.    


-- employees 테이블에서 first_name 의 값이 첫글자가 'J'로 시작하는 사원들만 

-- 모든 정보를 나타내세요.

-- like의 특별한 기능 

select *

from employees

where first_name like 'J%'; --  first_name의 칼럼이 시작되는 것이 J 인것을 출력

-- like 연산자와 함께 사용되어지는 %는 wild character 라고 부르는데, 그 뜻은 글자가 있든지 없든지 상관없다 라는 뜻.


select *

from employees

where first_name like '%s'; -- first_name의 칼럼이 끝나는 것이 s 인것을 출력

       

select *

from employees

where first_name like '%ee%'; -- first_name의 칼럼이 붙어있는 ee를 출력


select *

from employees

where first_name like '%e%e%'; -- 붙어있는 ee나 e와 e사이에 떨어져있는 것을  출력 (e가 2개 이상만 나온다.1개는 안나옴. 조건자체가 %e%e% 기 때문에 e 가2개만)

    

      

--like 연산자와 함께 사용하는 _ (언더바)는 아무글자 1개를 뜻한다.

--like 연산자와 함께 사용하는 % 는 글자가 있든 없든 관계없다는 말.        -- % 에는 어떤것이든 와도 된다는 것인뜻.

       

select first_name, last_name, department_id

from employees

where last_name like 'F_e%'; -- 첫번째 글짜는 F 그 뒤는 어떤글자든 _ 1자가 나와야하고 3번째 글짜는 e가 나온후 그 뒤는 아무거나 나와도됨.



--[문제] employees 테이블에서 성별이 여자만 

-- 사원번호, 사원명, 주민번호를 나타내세요

select department_id 사원번호,

        first_name || ' ' || last_name as 사원명, 

        jubun as 주민번호

from employees

where jubun like '______2%' or --and 는 둘다 충족해야되기 때문에 or만 가능.

       jubun like '______4%';



create table tbl_watch  -- watch 테이블 생성

(

watchname varchar2(30)

,bigo      varchar2(200)

);


insert into tbl_watch values('금시계','순금 99.99% 함유 고급시계');        -- 행 삽입

insert into tbl_watch values('은시계','고객만족도 99.99점 획득 고급시계'); -- 행 삽입


select *

from tbl_watch;


---- DML(Data Manuplation Language) 문 -------

--> 데이터조작어 : insert, upbate, delete, merge 

--> DML문은 기본적으로 수동 commit 이다.

-- 그러므로 명령(insert, upbate, delete, merge)을 내린다음에 

-- commit 이나 rollback 을 해주어야 한다.

-- commit(디스크에저장) rollback(취소)


rollback; -- 취소됨.


select *  --메모리에 올라간것만 보는것. 디스크에 저장하려면 commit

from tbl_watch;


insert into tbl_watch values('금시계','순금 99.99% 함유 고급시계');        

insert into tbl_watch values('은시계','고객만족도 99.99점 획득 고급시계');


commit; -- commit 되면 디스크에서 읽어옴. rollback을 할수없다.


--근데 금시계를 없애고싶다. 그때엔 delete를 이용하자


delete from tbl_watch; -- where절을 안쓰면 모든행이 삭제됨.. 


--그런데 다시 취소할수 있다. rollback 으로! (commit을 안했으니까)


rollback;


delete from tbl_watch 

where watchname='금시계'; -- where를 이용해 금시계부분만 삭제한다.


select *  

from tbl_watch;


update tbl_watch set bigo = '몰라';


rollback;


update tbl_watch set bigo='몰라'

where watchname ='금시계'; -- 금시계 부분만 bigo를 몰라로 바꿔라.


rollback;


select *  

from tbl_watch;


--*** rollback 과 commit 을 이해하고, insert와 delete를 이해하자.


--tbl_watch 테이블에서 bigo 컬럼에 99.99% 라는 글자가 들어있는 행만 추출 하세요.

-- (99.99% 에 %는 와일드캐릭터가 아니라 순수한글자 %인것을 추출하는것이 포인트.)

select *

from tbl_watch

where bigo like '%99.99/%%' escape '/'; -- 와일드캐릭터에서 빠져나간다 (escape) 뒤에 '/' 글자를 설정하고 /뒤에 한자만 와일드캐릭터를 빠져나간다는뜻 (설정하는글자는 아무거나도 가능함)


select *

from tbl_watch

where bigo like '%99.99a%%' escape 'a'; --설정은 아무거나 가능.



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

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

         

    >>>>>>>> 단일행 함수 <<<<<<<<

 

 ※단일행 함수의 종류

 1. 문자함수

 2. 숫자함수

 3. 날짜함수

 4. 변환함수

 5. 기타함수


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


1. 문자함수 

  1.1 lower

  1.2 upper

  1.3 initcap

  1.4 substr : 문자열중 특정문자 또는 문자열의 일부분을 선택할때 사용함

  


  select 'KH정보교육원',

          substr('KH정보교육원',3,2), -- 3은 3부터 시작점 / 2는 나타내는 글자수 2글자 = 정보

          substr('KH정보교육원',3)    -- 3은 3부터 시작점이고 글자수를 안잡아주면 끝까지 나옴.

  from dual;

          



--[문제] employees 테이블에서 성별이 남자만 

-- 사원번호, 사원명, 주민번호를 나타내세요

select department_id 사원번호,

        first_name || ' ' || last_name as 사원명, 

        jubun as 주민번호

from employees

where substr(jubun,7,1)=1 or  -- 7부터 시작해서 1글자가 1이거나 

       substr(jubun,7,1)=3;    -- 3인 조건의 사람만.


select department_id 사원번호,

        first_name || ' ' || last_name as 사원명, 

        jubun as 주민번호

from employees

where substr(jubun,7,1) in('1','3'); -- 위랑 같은말.


1.5 length : 문자열의 길이를 알려주는 것.


select length('kh정보교육원'),length('korea')

from dual;


1.6 lengthb : 문자열의 바이트수를 알려주는것

select lengthb('kh정보교육원'),lengthb('korea') -- lengthb = 바이트알아보기. 한글은 3바이트로...

from dual;


1.7 instr : 어떤 문자열에서 명명된 문자의 위치를 알려주는 것 (위치값 어디에있냐)

select instr('kh정보교육원 국가정보원 정보문화사', '정보', 1, 1)   -- 2번째 정보는 '정보'가 나오는곳찾는것 3번째위치의 1은 맨앞부터의 출발점. 4번째 1번의 위치는 정보라는 글자가 첫번째 나오는곳부터 출발. 

       ,instr('kh정보교육원 국가정보원 정보문화사', '정보', 1, 2)  -- 4번째의 1은 2번째 정보가 나오는 곳부터 출발.

       ,instr('kh정보교육원 국가정보원 정보문화사', '정보', 4, 1)

       ,instr('kh정보교육원 국가정보원 정보문화사', '정보', 4, 3)

       ,instr('kh정보교육원 국가정보원 정보문화사', '정보', 1)  --안쓰면 무조건 뒤는 ,1 임.

       ,instr('kh정보교육원 국가정보원 정보문화사', '정보', 4)

       

       ,instr('kh정보교육원 국가정보원 정보문화사', '정보', -1, 1)   -- 3번째 숫자가 -1 (음수) 이면 역방향으로 읽어드린다.   

       ,instr('kh정보교육원 국가정보원 정보문화사', '정보', -1, 2)  

       ,instr('kh정보교육원 국가정보원 정보문화사', '정보', -4, 1)

       ,instr('kh정보교육원 국가정보원 정보문화사', '정보', -4, 3)

       ,instr('kh정보교육원 국가정보원 정보문화사', '정보', -1)  

       ,instr('kh정보교육원 국가정보원 정보문화사', '정보', -4)

from dual;


1.8 reverse : 어떤 문자열을 거꾸로 보여주는 것이다.

select 'ORACLE', reverse('ORACLE'),

        '대한민국', reverse('대한민국') -- 액박뜸

        ,reverse(reverse('대한민국')) --꺼꾸로를 다시 꺼꾸로하면 나옴

from dual;




create table tbl_files

(fileno number(3)

,filepath varchar2(100)

);


insert into tbl_files values(1,'c:\documents\resume.hwp');

insert into tbl_files values(2,'d:\music.mp3');

insert into tbl_files values(3,'c:\myphoto\abc\def\myface.jpg');


select *

from tbl_files;


commit;


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

-- [문제] 아래와 같이 나오도록 하세요.

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

파일번호     파일명

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

    1       resume.hwp

    2       music.mp3

    3       myface.jpg

  [힌트] substr,instr,reverse  



select fileno, reverse(filepath),

        substr(reverse(filepath),1,?) -- ? 자리는 글자수를 뽑야낼 개수의 자리임.. 그걸 뽑아야한다.

from tbl_files;



select fileno, reverse(filepath),

        instr (reverse(filepath),'\',1) -1 -- 뽑아야할 글자수가 나왔음.

from tbl_files;



select fileno as "파일번호", reverse(filepath),

        substr(reverse(filepath),1, instr (reverse(filepath),'\',1) -1) ,

          reverse ( substr(reverse(filepath),1, instr (reverse(filepath),'\',1) -1) ) as "파일명" -- 다시 글자 돌리기.

from tbl_files;



--다른방법

select fileno as "파일번호",

        filepath as "파일명",

        instr(filepath, '\', -1)

from tbl_files;


select fileno as "파일번호",

        filepath as "파일명",

        instr(filepath, '\', -1),

        substr(filepath,instr(filepath, '\', -1)+1) as "파일명"

from tbl_files;


select fileno as "파일번호",

        substr(filepath,instr(filepath, '\', -1)+1) as "파일명"

from tbl_files;

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


1.9  lpad : 왼쪽부터 문자를 채움

1.10 rpad : 오른쪽부터 문자를 채움


select lpad('정보교육원', 20, '*') -- 숫자는 20바이트를 의미함 바이트확보크기를 의미. 한글=2바이트로 인식. 남은바이트를 *(별)로 채우라는 이야기 왼쪽부터..

       ,rpad('정보교육원', 20, '*') -- 남은바이트를 *(별)로 채우라는 이야기 오른쪽부터..

from dual;


--[문제] 대한민국이 연속해서 5번나오게 해보시오

select lpad(' ',41,'대한민국'), --' '을 기준으로 왼쪽에 채움.

        rpad('대한민국',40,'대한민국')

from dual;


select lpad('대한민국',length('대한민국')*2*5,'대한민국') -- length 길이 = 4 

from dual;


1.11 ltrim : 왼쪽부터 문자를 제거하는 함수. 

1.12 rtrim : 오른쪽부터 문자를 제거하는 함수.


select ltrim('aabccdadsabcd','abcd'), -- 왼쪽부터 a,b,c,d 중 해당되는것들을 모두 제거하고 해당되지않는 곳에서 멈춘다음에 출력됨.

        rtrim('aabbbtddabca', 'abcd')  -- 오른쪽부터 a,b,c,d 중 해당되는것들을 모두 제거하고 해당되지 않는 곳에서 멈춘다음에 출력됨. 

from dual;



select 'KH'|| '                  정보         교육원',

        'KH'|| ltrim('                  정보         교육원') , --제거해야할 글자를 안써주면 공백을 제거해줌.

        rtrim('             KH        ')|| '정보         교육원' --제거해야할 글자를 안써주면 공백을 제거해줌.

        from dual;

        

1.13 translate

  select translate('010-3456-0987' -- 요런식으로 바꿀껀데 // 영일영-삼사오육-영구팔칠

                    ,'0123456789'     -- 0은 영 1은 1로 바꿀거라는것.

                    ,'영일이삼사오육칠팔구') 

  from dual;

  

1.14 replace

  select replace('KH정보교육원 교육진흥원 서울교육대학교' ,'교육', 'education') -- 교육이라는 글자를 찾아서 eduation 으로 바꿔라.

  from dual;


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


  select *

  from tbl_member_test;

  

  insert into tbl_member_test values('kimys','abcd','김유신','서울');

  insert into tbl_member_test values('leess','abcd','이순신','서울');

  insert into tbl_member_test values('young2','abcd','이영이','서울');

  insert into tbl_member_test values('leesa','abcd','이에리사','서울');

  insert into tbl_member_test values('park','abcd','박이남','서울');

  insert into tbl_member_test values('leebon','abcd','이본','서울');


commit;


--[문제] : tbl_member_test 테이블에서 성이 '이'씨인 사람만

--        성을 '리'씨로 변경(update)하세요.

-- 바꾼다고 replace만 쓰는것이 아님!!!!!! ******************************


  update tbl_member_test set name = '리' || substr(name,2) -- '리' ||(붙이기) substr(name에서,2번째부터끝까지) *** 

  where name like '이%'; -- name 중 이씨를 범위로잡음

  

commit;

  









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


2. 숫자함수

    mod(5,2) -- mod 5를 2로 나누었을때의 나머지.

    trunc(5/2) -- trunc 는 5를 2로 나누었을때의 몫 소수점은 다 짜른다.


select 5/2, 

        mod(5,2) -- mod 5를 2로 나누었을때의 나머지.

       ,trunc(5/2) -- trunc 는 5를 2로 나누었을때의 몫 소수점은 다 짜른다.

from dual;


--연봉을 별로 표현해서 보기쉽게 하겠다. * = 10000

select employee_id as 사원번호,

        first_name || ' ' || last_name as 사원명,

        nvl(salary+(salary*commission_pct), salary)*12 as "연봉", 

        department_id as 부서번호,

        

        lpad('*',trunc(nvl(salary+(salary*commission_pct), salary)*12 /10000) ,'*') as "*1개는 1만임"

        --trunc(nvl(salary+(salary*commission_pct), salary)*12 /10000) -- 소수분을 필요없다 몫만 취하자.

        

from employees;


숫자함수 2016라인부터 다시 있음

2.3 부터 


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

5. 기타함수


5.1 case when then else end

  --case 다음에 조건식이 온다.

  select case 5-2  -- 이값이

          when 1 then '5-2=1 입니다.' -- 위 case값이 (when)1이 참이라면. then 을 출력하라. 그것도아니라면 다시 when

          when 3 then '5-2=3 입니다.' -- 위 case값이 (when)1이 참이라면. then 을 출력하라. 그것도아니라면 else

          else '나는 산수를 몰라요 ㅠㅠ'

          end

  from dual;

  

  select case 

          when 5-2 > 3 then '5-2 >3 입니다.' --when 값이 참이면 then뒤를 출력

          when 5-2 > 2 then '5-2 >2 입니다.' -- 마찬가지.

          else '나는 산수를 몰라요 ' -- 위 when들이 모두 거짓이면 else를 출력

          end        

  from dual;

  

  

5.2 decode

-- case와 비슷함

  select decode(5-2, 2, '5-2=2 입니다.'--1번째가 2번째와 같으면 3번째거를 출력 아니면 밑으로

                    , 3, '5-2=2 입니다.'--마찬가지로  아니면 밑에거 출력 

                       , '나는 산수를몰라요')  --모두아닐때 출력

                       

 5.3 rank, dense_rank      

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

                 

--[문제]--      

-- employees 테이블에서 부서번호 50번과 80번에 근무하는 사원들에 대해서 

-- 사원번호, 사원명, 부서번호, 성별을 나타내세요


select employee_id 사원번호,

        first_name|| ' ' ||last_name 사원명,

        department_id 부서번호,

        case substr(jubun, 7, 1)

              when '1' then '남' 

              when '3' then '남' -- 7번째 자리주번이  1이나 3이면 남 

              else '여' -- 나머지는 모두 여자

              end as 성별 -- 그것을 다시 성별이라고 as로 명칭을 바꿈.

from employees

where department_id in(50,80);


--질의결과에서 칸마다 왼쪽맞춤은 숫자 오른쪽맞춤은 문자



select employee_id 사원번호,

        first_name|| ' ' ||last_name 사원명,

        department_id 부서번호,

        decode (substr(jubun, 7, 1),1,'남'

                                   ,3,'남'

                                     ,'여') as 성별

from employees

where department_id in(50,80);


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


  -----***** 로그인 처리를 해주는 쿼리문 작성 *****----- ****암기****암기****암기****암기****암기****암기

  

  

  select *

  from tbl_member_test;

  

  alter table tbl_member_test

  add constraint PK_tbl_member_test_id primary key(id);

  --tbl_member_test 테이블에서 id 컬럼에 primary key(기본키) 제약을 준것인데, 

  --이렇게 주면 id 컬럼에 null값은 들어오지 못하고, 반드시 고유한 값만 들어와야 한다.

  --즉 , 중복된 ID는 허락하지 않는 것이다.



insert into tbl_member_test

values('superman','pclass','송성학','경기도 평택시');




insert into tbl_member_test

values('superman','qwer','이상호','경기도 부천시'); -- primary key 제약 줘서 동일한거 또 생성 못함.


insert into tbl_member_test

values('batman','qwer','이상호','경기도 부천시');


insert into tbl_member_test

values('pretty','1234','강지혜','서울시 충무로');

commit;


select count(*) --count는 그 테이블에 조건에 만족하는 갯수를 말해줌.

from tbl_member_test;


select count(*) -- 졸라맨은 없다. 그러니까 0이 나옴.

from tbl_member_test

where id='zolaman';


select count(*)

from tbl_member_test

where id='superman' and passwd='abcd';


-- tbl_member_test 테이블에서 아이디와 암호가 일치하는 행이 

-- 존재하면 '로그인 성공' 이라고 나타내어 주고

-- 만약에 아이디는 존재하지만 암호가 틀리면 '암호가 틀립니다' 라고 나타내어 주고,

-- 존재하지 않는 아이디라면 '회원 가입부터 하세요!!' 라고 나타내어주고 싶다.


select case(select count(*)

              from tbl_member_test 

              where id='superman' and passwd ='pclass')

              when 1 then '로그인 성공' -- 1

              else( case( select count(*)

                          from tbl_member_test

                          where id='superman')

                when 1 then '암호가 틀립니다.' -- 0

                else '회원가입부터 하세요!!' -- -1

                end)

              end as "로그인 처리"

from dual;


-- 1=로그인 성공, 0=암호가 틀림, -1=회원가입부터


select decode( (select count(*) from tbl_member_test where id='superman' and passwd='pclass'), 1, '로그인성공(1)' -- 2번째꺼는 카운트가 1이면 (존재하면) 1을 반환함.

       ,decode( (select count(*) from tbl_member_test where id= 'superman'),1,'암호가틀려[0]'                      -- 이 카운트는 아이디만 비교해서 아이디부분이 1이면(존재하면) 0을 반환함.

                                                                                ,'회원가입부터해[-1]')) as "로그인처리"-- 두개다 정보가 없을때 -1이 나옴.                                                   

from dual; --요 4줄 암기해보자.



select decode(조건,값1,결과값1 -- 조건과 값1을 비교해서 같으면 결과값1을 반환함.

                   ,값2,결과값2 -- 조건과 값2를 비교해서 같으면 결과값2을 반환함.

                   ,값3,결과값3 -- 조건과 값3을 비교해서 같으면 결과값2를 반환함.

                       ,결과값4) -- 모두아닐때 결과값4를 반환.



--푸는과정

select decode( (id,passw),1,1

                  ,decode( (id), 1,0

                                  ,-1) )

from dual;



select decode( (select count(*)

                from tbl_member_test 

                where id='superman' and passwd='pclass'),1,1

                ,decode( (select count(*)

                          from tbl_member_test

                          where id='superman'), 1,0

                                                  ,-1) )

                                                  as "로그인처리"

from dual;





  

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


3. 날짜함수

 -  현재 오라클 서버 시스템의 시간을 알려준 것.


3.1 sysdate


select sysdate, -- 년 월 일

        current_date, --년 월 일

        localtimestamp,  -- 초단위까지나옴

        current_timestamp -- 어디지역인지 까지 나옴.

from dual;


  

select sysdate, to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss') --년 월 일 시 분 초 로 나옴.

from dual;


-- 날짜 + 숫자 = 날짜 

-- 날짜 - 숫자 = 날짜

-- 여기서 숫자의 단위는 일(日)수 이다.


-- 날짜 - 날짜 = 숫자

-- 숫자의 단위는 일수


select sysdate - 1 , sysdate , sysdate + 1 -- 일수가 늘어남. 

from dual;


select to_char(sysdate - 1 ,  'yyyy-mm-dd hh24:mi:ss') as "어제"

        ,to_char(sysdate    ,  'yyyy-mm-dd hh24:mi:ss')  as "현재시각"

        ,to_char(sysdate + 1 ,  'yyyy-mm-dd hh24:mi:ss') as "내일"

from dual;

  

--[문제] 현재시각으로 부터 1일 2시간 3분 4초 뒤를 나타내세요.



select to_char(sysdate ,  'yyyy-mm-dd hh24:mi:ss') as 현재

        ,to_char(sysdate +1.08546296296296296296296296296296296296  ,  'yyyy-mm-dd hh24:mi:ss')  as "1일 2시간 3분 4초 뒤" --초로바꿔서 다시계산함...

from dual;


select to_char(sysdate ,  'yyyy-mm-dd hh24:mi:ss') as 현재

       ,to_char(sysdate+1+2/24+3/(24*60)+4/(24*60*60)   ,  'yyyy-mm-dd hh24:mi:ss')  as "1일 2시간 3분 4초 뒤 2"  -- 일수로 계산해서 간편하게함...

from dual;

 


3.2 add_months

--개월수를 더하거나 빼는것


select add_months(sysdate, -2) --현재 날짜에서 2달을 뺀 달

      , sysdate

      , add_months(sysdate, 2) -- 현재 날짜에서 2달을 더한 달

from dual;



-- [문제] 오늘 부로 송성학씨가 또 군대에 끌려간다.

--        군복무 기간이 21개월을 한다라고 가정하면

--        첫번째, 제대일자를 구하시고,

--        두번째, 제대일자까지 먹어야할 짬밥의 그릇수를 구하시오.

--        (단, 1일 3끼를 먹는다.)


select add_months(sysdate, 21) as "제대일자"

       ,add_months(sysdate, 21) - sysdate as "근무일수"

       ,(add_months(sysdate, 21) - sysdate) *3 as "그릇 수"

from dual;


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




--[문제] 현재시각으로 부터 2016년 10월 12일 21:00시까지 남은 기간을 

--       몇일 몇시간 몇분 몇초 로 나타내세요.


-- 일단 모든시간을 초로 바꿔서 다시 일수, 시간, 분, 초 로 바꿔야한다.

      

      --하루*하루의시간*한시간의분*1분의초

select 1*24*60*60 + 2*60*60 + 3*60 + 4

from dual; -- 93784 초

-- 1일 2시간 3분 4초를 초로 나타내어 본다.




183초

select 185/60, trunc(185/60)||'분', mod(185,60)||'초'

from dual;



3.3 trunc  , mod  -- trunc = 나누었을때 몫 trunc(/), mod 나누었을때 나머지 mod(,) 

 

select trunc(trunc(trunc(93784/60)/60)/24)||'일'||mod(trunc(trunc(93784/60)/60),24)||'시간',

        trunc(trunc(93784/60)/60)||'시간'||mod(trunc(93784/60),60),

        trunc(93784/60)||'분'|| mod(93784,60)||'초'

from dual;



select 1*(24*60*60), --하루에 대한 초

        2*(24*60*60) --이틀에 대한 초

from dual;




select '2016-10-12 21:00:00' - sysdate

from dual; --안됨 문자타입이라. 변환함수를 쓰자.


select to_date('2016-10-12 21:00:00','yyyy-mm--dd hh24:mi:ss') - sysdate --'yyyy-mm--dd hh24:mi:ss' 한타입으로 된 문자를 날자로 바꾸라는 변환함수 to_date

from dual;



select trunc((to_date('2016-10-12 21:00:00','yyyy-mm--dd hh24:mi:ss') - sysdate)*(24*60*60))

from dual;



select trunc(trunc(trunc((1*24*60*60 + 2*60*60 + 3*60 + 4)/60)/60)/24)||'일'||mod(trunc(trunc(93784/60)/60),24)||'시간'

        ||mod(trunc(93784/60),60)||'분'|| mod(93784,60)||'초'

        

from dual;



select trunc(trunc(trunc(trunc( (to_date('2016-10-12 21:00:00','yyyy-mm-dd hh24:mi:ss') - sysdate) * (24*60*60) )/60)/60)/24)||'일 '||

              mod(trunc(trunc(trunc( (to_date('2016-10-12 21:00:00','yyyy-mm-dd hh24:mi:ss') - sysdate) * (24*60*60) )/60)/60),24)||'시간 '||

              mod(trunc(trunc( (to_date('2016-10-12 21:00:00','yyyy-mm-dd hh24:mi:ss') - sysdate) * (24*60*60) )/60),60)||'분 '||

              mod(trunc( (to_date('2016-10-12 21:00:00','yyyy-mm-dd hh24:mi:ss') - sysdate) * (24*60*60) ), 60) ||'초'

   from dual;


create table tbl_auction

(auction_no   number

,expire_date  date

);


insert into tbl_auction values

(1, to_date('2016-05-12 21:00:00','yyyy-mm-dd hh24:mi:ss'));


insert into tbl_auction values

(2, to_date('2016-05-13 11:30:00','yyyy-mm-dd hh24:mi:ss'));


insert into tbl_auction values

(3, to_date('2016-05-14 20:00:00','yyyy-mm-dd hh24:mi:ss'));



select auction_no, to_char(expire_date,'yyyy-mm-dd hh24 mi:ss') as expire_date

from tbl_auction;


commit;



--[문제] 해당 테이블을 조회했을때 

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

경매번호    종료시각              남은기간

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

1         2016-05-12 21 00:00     일 시간 분 초

2         2016-05-13 11 30:00

3         2016-05-14 20 00:00



select auction_no as "경매번호", 

         to_char(expire_date, 'yyyy-mm-dd hh24:mi:ss') as "종료시각",

         trunc( trunc( trunc((expire_date - sysdate)*(24*60*60)/60)/60 )/24 )||'일 ' ||

          mod( trunc( trunc((expire_date - sysdate)*(24*60*60)/60)/60 ), 24)||'시간 ' ||

          mod( trunc((expire_date - sysdate)*(24*60*60)/60), 60)||'분 ' || 

          round( mod( (expire_date - sysdate)*(24*60*60), 60) )||'초'

         as "남은기간" 

from tbl_auction;


--(expire_date - sysdate)*(24*60*60)




--------------------------------------------------------------------- 0일 미만만 보고싶을때 -- 조건 where 절에 간단하게 하기위해 view를 만듬.


---------------- 저장된뷰라고 부름 stored view -----------------------********

create or replace view view_auction  -- 컬럼을 view_auction 테이블처럼 보겠다는것

as

select auction_no, 

         to_char(expire_date, 'yyyy-mm-dd hh24:mi:ss') as expire_date,

         trunc( trunc( trunc((expire_date - sysdate)*(24*60*60)/60)/60 )/24 )||'일 ' ||

          mod( trunc( trunc((expire_date - sysdate)*(24*60*60)/60)/60 ), 24)||'시간 ' ||

          mod( trunc((expire_date - sysdate)*(24*60*60)/60), 60)||'분 ' || 

          round( mod( (expire_date - sysdate)*(24*60*60), 60) )||'초'

         as nameungigan

from tbl_auction;


select *

from view_auction; --마치 테이블처럼 나온다.


--하루가 안되어진것만 보자.


select nameungigan     

from view_auction

where to_number(substr(nameungigan,1,instr(nameungigan,'일',1)-1)) < 1 ;  -- to number는 문자정보를 숫자로 바꿔준다


-- 칼럼들을 테이블로 바라보게 view를 만들고 , 조건절을 넣어서 처리함.


select * from tab; --모든테이블보기


desc view_auction; -- 테이블의 칼럼과 데이터타입유형보기


-- view_auction의 원본 소스를 조회해 보자.

select *

from user_views

where view_name='VIEW_AUCTION'; -- view_auction의 원본 소스를 조회 


select *

from user_views

where view_name='EMP_DETAILS_VIEW'; --EMP_DETAILS_VIEW 의 원본소스 조회



3.4 extract -- 날짜에서 년,월,일을 추출해주는 함수이다.


select sysdate,

        extract(year from sysdate) as "년1" -- 현재 날짜에서 년만 빼오겠다.

       ,to_char(sysdate, 'yyyy') as "년2"

       ,extract(month from sysdate) as "월1"-- 현재 날짜에서 월만 빼오겠다.

       ,to_char(sysdate, 'mm') as "월2"

       ,extract(day from sysdate) as "일1"--현재 날짜에서 날만 빼오겠다

       ,to_char(sysdate, 'dd') as "일2"

from dual;


-- 결과는 같은데 to_char 는 문자타입

-- extract 는 숫자타입 

-- 연산할때는 숫자타입인 extract 를 쓰자.



-- employees 테이블에서 

-- 사원번호,사원명,주민번호,성별, 생년,나이 구하기.


select employee_id as "사원번호"

       ,first_name|| ' ' || last_name as"사원명"

       ,jubun as "주민번호"

       ,case when substr(jubun,7,1) in('1','3') then '남' else'여' end as "성별"

       ,case when substr(jubun,7,1) in('1','2') then 1900 else 2000 end + to_number(substr(jubun,1,2)) as "생년" -- 주번컬럼은 문자열로 되있어서 to_number로 숫자로 바꾼다음에 구함.

       ,extract(year from sysdate)-(case when substr(jubun,7,1) in('1','2') then 1900 else 2000 end + to_number(substr(jubun,1,2)))+1 as "현재나이" -- extract 로 현재 년도를 빼와서 나이를뺀다.

from employees;




-- employees 테이블에서 여자중 나이가 20대와 40대만 

-- 사원번호, 사원명, 주민번호, 성별, 나이 나타내세요.

-------********************************************** 잘 기 억 합 시 다 ! *********************

------------------ inline view를 사용한 쿼리문 작성. 


--전체 괄호하기-> 이름짓기 -> 자바처럼 이름. 으로 접근하기.-------********************************************** 잘 기 억 합 시 다 ! *********************

select V.*

from

(

select employee_id 

       ,first_name|| ' ' || last_name as ename

       ,jubun

       ,case when substr(jubun,7,1) in('1','3') then '남' else'여' end as gender

       ,extract(year from sysdate)-(case when substr(jubun,7,1) in('1','2') then 1900 else 2000 end + to_number(substr(jubun,1,2)))+1 as age

from employees

) V -- inline view 테이블로 간주하게끔 괄호 하고 이름을 정함. 괄호전체가 V 임.

where V.gender = '여' and trunc( V.age / 10 ) in (2,4) -- age를 10으로 나눈값의 몫만 취해서 2또는 4 찾기.

order by V.age ;-- 오름차순으로 

      

 

 

 

 3.5 last_day(날짜)  --> 해달날짜가 포함된 달에 마지막 날짜(일)를 알려주는 것.

 

 select last_day(sysdate) -- 이번달의 마지막날짜. 

 from dual;

 

 select last_day('2016-02-01') -- 지정한 날짜의 마지막날짜. 

 from dual;

 

 select last_day(to_date('2016-02-01','yyyy-mm-dd')) 

        ,last_day(to_date('2015-02-01','yyyy-mm-dd')) 

 from dual;

 

 

 

 select sysdate, to_char(sysdate,'day'), to_char(sysdate, 'dy')  -- 요일을 나타나는것! 보여줄때만쓰자.

 from dual;

 

  select sysdate, to_char(sysdate,'d')

  -- to_char(sysdate,'d') 값이  

-- 1:일 , 2:월 , 3:화 , 4:수 , 5:목 , 6:금 , 7:토

 from dual;

 

 

 select last_day(to_date('2016-07-25','yyyy-mm-dd')) -- 7월이 포함된 달력에서..(마지막날)

        ,to_char(last_day(to_date('2016-07-25','yyyy-mm-dd')),'d') -- 그날(마지막날) 의 요일구하기.

 from dual;

 

 

 select case 

        to_char(last_day(to_date('2016-07-25','yyyy-mm-dd')),'d')

        when '1' then last_day(to_date('2016-07-25','yyyy-mm-dd')) + 1

        when '7' then last_day(to_date('2016-07-25','yyyy-mm-dd')) + 2

        else last_day(to_date('2016-07-25','yyyy-mm-dd'))

        end as "이자내는날"

 from dual;

 

 select case 

        to_char(last_day(to_date('2016-12-25','yyyy-mm-dd')),'d')

        when '1' then last_day(to_date('2016-12-25','yyyy-mm-dd')) + 1

        when '7' then last_day(to_date('2016-12-25','yyyy-mm-dd')) + 2

        else last_day(to_date('2016-12-25','yyyy-mm-dd'))

        end as "이자내는날"

 from dual;

 

 

 --[문제] employees 테이블에서 

 --

 --     정년퇴직일, 정년퇴직행사일 을 나타내세요. 

 -- 정년 퇴직일이라함은 [교육공무원법상] 

 -- 해당 사원의 생일이 3월에서 8월에 태어난 사람은 해당사원의 나이(한국나이 {+1} )가 63세가 되는 년도에

 -- 8월 31일으로 하고,

 --  해당 사원의 생일이 9월에서 2월에 태어난 사람은 해당사원의 나이(한국나이 {+1} )가 63세가 되는 년도에

 -- 2월말일 (2월 28일 또는 2월 29일)으로 한다.

 

 -- 정년 퇴직 행사일은 [내가 맘대로지은 법] 

 -- 정년 퇴직일에 해당하는 요일이 토,일 이라면 그전 금요일로 한다.

 -- 정년 퇴직일에 해당하는 요일이 월~금 이라면 그냥 그대로 한다.


 

select V.*,

  to_char(last_day(to_date(to_char(add_months(sysdate, (63-V.age)*12),'yyyy-') || 

       case when to_number(substr(V.jubun,3,2)) between 3 and 8 then '08-01'

              else '02-01' end ,'yyyy-mm-dd')) , 'yyyy-mm-dd')    

          as expire_date

from

(

select  employee_id as"사원번호"

        ,jubun

        ,first_name|| ' ' ||last_name as ename

        ,extract(year from sysdate) - (case when substr(jubun,7,1) in('1','2') then 1900 else 2000 end +to_number( substr(jubun,1,2))) +1 as age

        

        

from employees

) V;


 


3.6 months_between -- 두 날짜의 개월차이를 알려주는 것. 앞에꺼에서 뒤에껄 빼는거임!!



select months_between( add_months(sysdate, 5), sysdate)

from dual;




select V.employee_id as "사원번호"

       ,V.ename as "사원명"

       ,V.jubun as "주민번호"

       ,V.age as "현재나이"

       ,V.monthsal as "월급"

       ,V.hire_date as "입사일자"

       ,to_char(last_day(to_date(to_char(add_months(sysdate, (63-V.age)*12),'yyyy-') || 

                   case when to_number(substr(V.jubun,3,2)) between 3 and 8 then '08-01'

                  else '02-01' end ,'yyyy-mm-dd')) , 'yyyy-mm-dd')   as "정년퇴직일자"

       -- months_between(to_date( ?정년퇴직일자? ,'yyyy-mm-dd' ),V.hire_date) /12  --나누기 12는 퇴직금 이 년별로 구해야하는거기때문에 소수부가 나옴. 그걸짜르기위해서 

       -- trunc( months_between(to_date( ?정년퇴직일자? ,'yyyy-mm-dd' ),V.hire_date) /12 )

       -- trunc( months_between(to_date( ?정년퇴직일자? ,'yyyy-mm-dd' ),V.hire_date) /12 ) * V.monthsal -- 월급을 뒤에 곱하면 예상 퇴직금!

       ,trunc(months_between(to_date((to_char(last_day(to_date(to_char(add_months(sysdate, (63-V.age)*12),'yyyy-') || 

                   case when to_number(substr(V.jubun,3,2)) between 3 and 8 then '08-01'

                  else '02-01' end ,'yyyy-mm-dd')) , 'yyyy-mm-dd')) ,'yyyy-mm-dd' ),V.hire_date) /12 ) * V.monthsal    as "예상 퇴직금"

from

(

select  employee_id 

        ,jubun

        ,first_name|| ' ' ||last_name as ename

        ,nvl(salary + (salary * commission_pct), salary) as monthsal

        ,hire_date

        ,extract(year from sysdate) - (case when substr(jubun,7,1) in('1','2') then 1900 else 2000 end +to_number( substr(jubun,1,2))) +1 as age

        

from employees

) V;


3.7 next_day -- 1932라인에 있음




--[문제]  employees 테이블에서 예상퇴직금이 300000 이상인 사원들만 

-- 사원번호 , 사원명, 입사일자, 정년퇴직일자, 예상퇴직금을 나타내세요. 


create or replace view view_retireinfo  -- 테이블처럼 이미만들어진inline view를  stored view처럼 뷰를 만드는 소스 ******~~~ 

as

select V.employee_id 

       ,V.ename

       ,V.jubun 

       ,V.age

       ,V.monthsal 

       ,V.hire_date 

       ,to_char(last_day(to_date(to_char(add_months(sysdate, (63-V.age)*12),'yyyy-') || 

                   case when to_number(substr(V.jubun,3,2)) between 3 and 8 then '08-01'

                  else '02-01' end ,'yyyy-mm-dd')) , 'yyyy-mm-dd')   as retireday

       -- months_between(to_date( ?정년퇴직일자? ,'yyyy-mm-dd' ),V.hire_date) /12  --나누기 12는 퇴직금 이 년별로 구해야하는거기때문에 소수부가 나옴. 그걸짜르기위해서 

       -- trunc( months_between(to_date( ?정년퇴직일자? ,'yyyy-mm-dd' ),V.hire_date) /12 )

       -- trunc( months_between(to_date( ?정년퇴직일자? ,'yyyy-mm-dd' ),V.hire_date) /12 ) * V.monthsal -- 월급을 뒤에 곱하면 예상 퇴직금!

       ,trunc(months_between(to_date((to_char(last_day(to_date(to_char(add_months(sysdate, (63-V.age)*12),'yyyy-') || 

                   case when to_number(substr(V.jubun,3,2)) between 3 and 8 then '08-01'

                  else '02-01' end ,'yyyy-mm-dd')) , 'yyyy-mm-dd')) ,'yyyy-mm-dd' ),V.hire_date) /12 ) * V.monthsal    as retiremoney

from

(

select  employee_id 

        ,jubun

        ,first_name|| ' ' ||last_name as ename

        ,nvl(salary + (salary * commission_pct), salary) as monthsal

        ,hire_date

        ,extract(year from sysdate) - (case when substr(jubun,7,1) in('1','2') then 1900 else 2000 end +to_number( substr(jubun,1,2))) +1 as age

        

from employees

) V;


select *

from view_retireinfo

where retiremoney >=300000; -- 간단하게 추가한 뷰를 가지고 조건을 정해 간단한 소스로 원하는부분(퇴직금이 30만이상인 사람) 만 뽑아냄.


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

---------기타함수 5.3부터 추가되는 내용~

-- ****** 등수 : rank, dense_rank *******************

-- 예매율 가장좋은것, 물건이 가장 잘팔린것 에 응용할수있다.


5.3 rank, dense_rank 


select department_id as "부서번호"

       ,employee_id as "사원번호"

       ,first_name||' '||last_name as"사원명"

       ,salary as "기본급여"

from employees


-- 위에서 기본급여에 대한 등수를 구해보자~


select department_id as "부서번호"

       ,employee_id as "사원번호"

       ,first_name||' '||last_name as"사원명"

       ,salary as "기본급여"

       ,rank()over(order by salary desc) as "전체등수"--order by로 내림차순정렬 => 가장많은급여부터 내림차순으로 나옴

       ,rank()over(partition by department_id --부서 번호별로 칸막이를 쳤을때 등수를 구해라 =>  partition by 칸막이칠 기준

                    order by salary desc) as "부서내등수"

from employees

order by 1, 4 desc; -- 1번째컬럼은 오름차순(생략) , 4번째는 내림차순 ㄱㄱ

-- over() 는 범위. 어디에대한 등수가 나옴 1등,2등,3...... 이런식으로 ..

-- partition by 은 어디기준에서 칸막이를 치는것 


--ex)

-- 시험성적 등수                   내무반 서열

-- 강지혜 98     2                  넘버투     2

-- 송성학 100    1                  왕고참     1

-- 공현정 97     3                  넘버쓰리   3

-- 김수현 51     5                  넘버포     4

-- 오진석 97     3                  넘버쓰리   3

-- 서영학 10     6                  넘버파이브 5

-- 최재우 8      7                  넘버식스   6


--공동 3등이니 김수현은 5등이다 / 내무반 서열은 동기니까 서열은 같다.

-- 이럴때에는 dense_rank 를 쓴다. 서열을 구할때~



select department_id as "부서번호"

       ,employee_id as "사원번호"

       ,first_name||' '||last_name as"사원명"

       ,salary as "기본급여"

       ,rank()over(order by salary desc) as "전체등수"

       ,rank()over(partition by department_id 

                   order by salary desc) as "부서내등수"

        ,dense_rank()over(order by salary desc) as "전체서열" -- 몇등이 아니라 몇번째로 많이버냐를 구하는것 !

        --,dense_rank()over(partition by department_id 

        --           order by salary desc) as "부서내서열"

from employees;

--order by 1, 4 desc;


----


--[문제] 퇴직금에 대한 등수를 구해라

select *, dense_rank()over(order by reitremoney desc) as"퇴직금서열" -- 요렇게하면 모든것이 view_retireinfo 나오면서 퇴직금서열이 추가될것같지만 안됨.

from view_retireinfo;



select employee_id, ename, jubun, age, monthsal, hire_date, retireday, retiremoney,  --일일히 써줘야함.

        dense_rank()over(order by retiremoney desc) as "퇴직금서열"

from view_retireinfo;



--[문제] 위 문제에 연령대별 서열을 추가하시오. + ename, age, monthsal, retiremoney


select ename

        , age

        , trunc(age,-1)

      --,trunc(age/10)*10 --소수부 필요없으니 짜르고 몫에 10곱함

        , monthsal

        , retiremoney

        ,dense_rank()over(partition by trunc(age,-1) order by retiremoney desc) "연령대별 퇴직금서열"

        ,dense_rank()over(partition by (age/10)*10 order by retiremoney desc) "연령대별 퇴직금서열2"

        --dense_rank()over(order by retiremoney desc) as "퇴직금서열"

from view_retireinfo;



select ename

        , age

        , trunc(age/10)

        , trunc(age/10)*10  

        , trunc(age/10,1) -- 일.X 까지나와라

        , trunc(age/10,0) --  = trunc(age/10) 랑같은말.

        , trunc(age,0)   -- 현재 나이에서 소수부 짤러버려라 일 자리까지 나와

        , trunc(age,-1)  -- 10자리까지를 잘라버려라 = trunc(age/10)*10 얘랑 같은말 

        , trunc(age,-2)  -- 100자리까지만 보여주고 나머지 잘러라

        , monthsal

        , retiremoney

        

        --dense_rank()over(order by retiremoney desc) as "퇴직금서열"

from view_retireinfo;


--[문제] 1등부터~ 10등 까지에 해당하는 사원만 나타내어보시오


select department_id as "부서번호"

       ,employee_id as "사원번호"

       ,first_name||' '||last_name as"사원명"

       ,salary as "기본급여"

       ,dense_rank()over(order by salary desc) as "전체등수"

from employees

where dense_rank()over(order by salary desc) <= 10; -- ** # rank , dense_rank 는 where 절 바로 쓸수없다. 인라인뷰에서 가능하다. # **



--그래서 아래처럼 인라인뷰를 형성해서 ㄱㄱ 

select V.*

from

(

select department_id as "부서번호"

       ,employee_id as "사원번호"

       ,first_name||' '||last_name as"사원명"

       ,salary as "기본급여"

       ,dense_rank()over(order by salary desc) as "전체등수"

from employees

)V

where V."전체등수" <= 10;


select V.*

from

(

select ename

        , age

        , trunc(age,-1) as ageline

      --,trunc(age/10)*10 as ageline --소수부 필요없으니 짜르고 몫에 10곱함

        , monthsal

        , retiremoney

        , dense_rank()over(order by retiremoney desc) as "퇴직금서열"

from view_retireinfo

)V

where V."퇴직금서열" <=5;


5.4 greatest , least   가장큰것 greatest, 가장작은것 least


select greatest(10,90,100,80) -- 괄호안에서 가장큰것

       ,least(10,90,100,80) -- 괄호안에서 가장작은것

from dual;


select greatest('김유신','윤봉길','허준','고두심') -- 가장 뒤에나오는것 

        ,least('김유신','윤봉길','허준','고두심')  -- 가장 앞에나오는것 (작으니까 앞에나오지)

from dual;


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

---------날짜함수 3.6부터 추가되는 내용~

-- ****** 3.7 next_day , 3.8 to_ym , to_dsinterval  *******************


3.7 next_day -- 돌아오는 요일명중 가장 빠른날을 알려주는 것.


select sysdate, next_day(sysdate, '토') --돌아오는 가장 빠른 토요일 

from dual;



select sysdate, next_day(sysdate, '토') --돌아오는 가장 빠른 토요일

                , next_day(sysdate, '월') --돌아오는 가장 빠른 월요일

                , next_day(sysdate, '금') --돌아오는 가장 빠른 금요일

from dual;


3.8 to_yminterval --년, 개월         ex) ('01-02')

    to_dsinterval --일, 시간,분,초    ex) ('003 04:05:06')

--현재일로부터 1년 2개월 3일 4시간 5분 6초 뒤를 나타내세요.


select add_months(sysdate, 1*12+2) +3 +4/24+ 5/(24*60)+6/(24*60*60) -- 요것이 1년 2개월 3일 4시간 5분 6초 뒤

from dual;


select to_char(add_months(sysdate, 1*12+2) +3 +4/24+ 5/(24*60)+6/(24*60*60) ,'yyyy-mm-dd hh24:mi:ss') as "1"

        ,to_char(sysdate + to_yminterval('01-02')+to_dsinterval('003 04:05:06'), 'yyyy-mm-dd hh24:mi:ss') as "2" --앞에 0은 생략가능하지만 쓴다. 1년은 365이기 떄문에 0은 3자리

      --  ,sysdate - to_yminterval('01-02') - 빼기는 1년2개월 전 

from dual;



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

---------숫자함수 2.1부터 추가되는 내용~

-- *************************


2.2 round : 반올림을 해주는 것.


select 94.547

       ,round(94.547) --0 을생략한거라 밑에거와 똑같음.

       ,round(94.547,0) 

       ,round(94.547,1) --소수부 첫째자리까지 보여주면서 나머지를 반올림

       ,round(94.547,-1) --10의자리까지만 보여주고 1의자리는 반올림한다

       ,round(94.547,-2) --100의짜리까지만 보여주고 10의짜리를 반올림한다

from dual;


2.3 trunc : 절삭해주는 것.

select 94.547

       ,trunc(94.547) --0 을생략한거라 밑에거와 똑같음.

       ,trunc(94.547,0) --10자리까지만 보여주고 나머지 짤라버린다 .

       ,trunc(94.547,1) --소수부 첫째자리까지 보여주면서 나머지를 짤라버린다.

       ,trunc(94.547,-1) --10자리까지만 보여주고 1자리는 짤라버린다.

       ,trunc(94.547,-2) --100짜리까지만 보여주고 10짜리를 짤라버린다.

from dual;


--테이블 생성

create table tbl_sungjuk

(hakbun     varchar2(10)

,jumsu      number(3)

);


--정보삽입

insert into tbl_sungjuk values('101',94);

insert into tbl_sungjuk values('102',89);

insert into tbl_sungjuk values('103',98);

insert into tbl_sungjuk values('104',69);

insert into tbl_sungjuk values('105',59);

insert into tbl_sungjuk values('106',100);


--최종확인

commit;


--조회

select *

from tbl_sungjuk




--[문제] ------------------- 아래와같이 나타내시오

  학번    점수    학점

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

101      94      A

102      89      B

103      98      A

104      69      D

105      59      F

106      100     A


90점대 = A

80점대 = B

70점대 = C

60점대 = D

이하   = F

-- case 문

select case trunc(jumsu,-1) when 100 then 'A' 

                              when 90 then 'A' 

                              when 80 then 'B' 

                              when 70 then 'C'

                              when 60 then 'D' 

                              else 'F' end as 학점

from tbl_sungjuk;


--decode 문

select

decode (trunc(jumsu,-1) , 100, 'A'

                        ,  90, 'A'

                        ,  80, 'B'

                        ,  70, 'C'

                        ,  60, 'D'

                            ,  'F' )as 학점

from tbl_sungjuk;


--

select case substr(trunc(jumsu,-1),1,3) when '100' then 'A' 

                              when '90' then 'A' 

                              when '80' then 'B' 

                              when '70' then 'C'

                              when '60' then 'D' 

                              else 'F' end as 학점

from tbl_sungjuk;



2.4 power 거듭제곱 


select 2*2*2*2*2, power(2,5) --2를 연속해서 5번곱해라

from dual;



2.5 sqrt 제곱근 (루트)


select sqrt(4), sqrt(2) ,sqrt(3)

from dual;



2.6 sign 결과값이 양수라면 1, 

                 0이라면 0,

                음수라면 -1

               

  

 select sign(5-2) --양수라 1

        ,sign(5-5) -- 0

        ,sign(2-5) --음수라 -1

from dual;

                

                

2.7 ascii 아스키코드 , chr 반대개념 


select ascii('A'),ascii('a'),ascii('0'),ascii(' ') -- 암기

from dual;


select chr(65),chr(97),chr(48),chr(32)

from dual;



2.8 sin, cos, tan, asin, acos, atan  삼각함수


select sin(90),cos(90),tan(90)

       ,asin(0.3),acos(0.3),atan(0.3)

from dual;



2.9 log 


select log(10,100)

from dual;


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

 4. 변환함수

 

4.1 to_char  숫자나 날짜를 문자타입으로 변환해주는것


--

select to_char(sysdate,'yyyy')

       ,to_char(sysdate,'mm')

       ,to_char(sysdate,'dd')

       ,to_char(sysdate,'hh24')

       ,to_char(sysdate,'hh am')

       ,to_char(sysdate,'hh pm')

       ,to_char(sysdate,'mi')

       ,to_char(sysdate,'ss')

from dual;


--

select to_char(sysdate,'q') as 분기 -- 쿼터        1월:1(분기), 4~6월:2, 7~9월:3, 10~12월:4

from dual;


--

select to_char(sysdate, 'day') "X요일"

       ,to_char(sysdate, 'dy') "X"

from dual;


--

select case to_char(sysdate,'d')

          when '1' then '일'

          when '2' then '월'

          when '3' then '화'

          when '4' then '수'

          when '5' then '목'

          when '6' then '금'

          when '7' then '토'

          end as " 오늘의 요일 "

from dual;


--

select (sysdate-to_date(to_char(sysdate,'yyyy-mm-dd'),'yyyy-mm-dd')) *(24*60*60)  --오늘밤 (0시0분0초)자정부터 현재까지의 초

      , to_char(sysdate,'sssss') -- 오늘밤 (0시0분0초)자정부터 현재까지의 초 * 위에거와 같다!

from dual;


--

select to_char(3000000, '9,999,999')  --자릿수만큼 9를 써주고 콤마찍을 위치에 찍어줌.

       ,to_char(3000000, '$9,999,999')

       ,to_char(3000000, 'L9,999,999') -- 앞에 대문자 L을 쓰면 각 나라의 돈의 단위가 나온다.

from dual;


--


select round(salary/12,1)

       ,to_char(round(salary/12,1),'9999.0') -- 자릿수가 통일되어서 정렬되어 나온다.

from employees;


4.2 to_date 문자를 날짜타입으로 변환해주는것


4.3 to_number 문자를 숫자타입으로 변환해주는것

select 2+to_number('3') --문자타입 '3'을 숫자타입으로 바꿔서 연산해줌  

from dual;












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


 --------- ***** 그룹함수 (집계함수) ***** ---------

 ------------- *@@@* { 중요!!!!! }  그룹함수(집계함수) 에서는 null은 무조건 제외하고서 연산을 한다. @@@@@*******


1.sum -- 합계

2.avg -- 평균

3.max -- 최대값

4.min -- 최소값

5.count -- select 되어서 나온 결과물의 행의 갯수

6.variance --분산

7.stddev --표준편차


-- 1.sum -- 합계 ----------------------

select count(salary) -- null 없음

from employees;


select count(commission_pct) --null있음.  null 아닌것의 갯수를 나타냄. 35개

from employees;


select commission_pct*salary 

from employees;


select sum(salary) -- null 없는놈의 합 

from employees;


select sum(commission_pct*salary)  -- 그룹함수는 null값을 빼고 연산한다.

from employees;

--


--2.avg -- 평균 ----------------------

select avg(salary) -- 평균 분모의 107이 들어가야 평균이나옴 null이없으니 이건 가능.

from employees; --107명


select avg(salary)

       ,sum(salary)/count(salary)

from employees;


select avg(commission_pct*salary) -- commission_pct null이있다. 널은 무조건 빼버리기 때문에  commission_pct은 35명만이다. => 이것은 commission_pct 수당을 받는 35명의 평균치다.

from employees;


select avg(commission_pct*salary)

       ,sum(commission_pct*salary)/count(commission_pct*salary)  --위와 같음.

from employees;


select sum(commission_pct*salary)/count(*) --모든컬럼의 가로줄이 모두 null일수가 없다. 그래서 이렇게 계산하면 모든사람의 수가 카운트된다.

from employees; 



--[문제] 우리회사의 평균 commission_pct을 구해야하는데 null인사람은 0으로 간주를 하고 평균을 구해보시오. -----------------------


--

select sum(nvl(commission_pct*salary,0))/count(*) --null값까지 0으로 던져주고 모든사람들을 평균치를 냈음.

       ,avg(nvl(commission_pct*salary, 0))         --null값까지 0으로 던져주고 모든사람들을 평균치를 냈음.

from employees; 


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



--[문제] employees 테이블에서 부서번호별 인원수를 나태내세요.  * * * * * group by 와 having 을 알아보자



--ex)-----------------------

부서번호     인원수 

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

10           2

20           3

30           5

40           3

50          12

......................

-- 이런식으로 나타내어 보자. 


select department_id as 부서번호

       ,count(*) as 인원수  --group by에 의해서 department_id끼리 묶은놈들의 카운트를 센다. 그것이 인원수가 됨.

from employees

group by department_id --department_id가 같은놈들끼리 그룹을 지은다음에~~ having은 그룹함수를 쓸때 사용함.

order by 1;



--[문제] employees 테이블에서 남녀별 인원수를 나타내세요. (힌트: 취하고자하는 컬럼이없으면 인라인뷰를 이용)


--ex)-----------------------

성별     인원수 

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

남자          X명

여자          X명


select V.gender as 성별

       ,count(*) as 인원수 -- 그룹으로 묶은상태의 카운트

from

(

select 

case when substr(jubun,7,1) in('1','3') then '남' else'여' end as gender 

from employees

)V

group by V.gender  -- gender 데이터중 같은놈끼리 묶어서 그룹을 지어준다.

order by 1 ;


--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 5.16 월

 

-- rollup을 해서 전체 인원수를 나타내주자

select department_id as 부서번호

       ,count(*) as 인원수   

from employees

group by rollup (department_id);  -- rollup은 (department_id)의 null 과 관계없다. 부서별로 묶지않고, 그냥 전체에 대한 인원수. 

 


--grouping을 해서 그룹여부를 조회하고 변경값을 부여.

select decode(grouping(V.gender), 0, V.gender

                                     ,'전체')as "성별"  -- grouping한 값이 0이라면 젠더를 나타내고 아니라면 '전체'라고 출력되게함. 

       ,count(*) as 인원수  

       ,grouping(V.gender)  -- 그룹이 됬는지 안됬는지 보여줌. 값이 0이나오면 메모리상에서 실제로 그룹을 지었다는말. 1값이나오면 그룹을 안지었다는 말. 

from

(

select 

case when substr(jubun,7,1) in('1','3') then '남' else'여' end as gender 

from employees

)V

group by rollup (V.gender); -- rollup을 쓰면 107이 나옴..

 


--남여 비율구하기

select decode(grouping(V.gender), 0, V.gender

                                     ,'전체')as "성별"  

       ,count(*) as 인원수                                               -- 칼럼에해당되는인원 / 전체인원 * 100(비율) = 비율구하는것

       ,round(count(*)/(select count(*) from employees)*100,1) ||'%' as 비율 --  56/107*100 이 비율구하는건데 107은 select count(*) from employees 로 전체인원수를 카운트세면 됨.

from

(

select 

case when substr(jubun,7,1) in('1','3') then '남' else'여' end as gender 

from employees

)V

group by rollup (V.gender); 

 


--부서번호에 전체를 넣기

select decode(grouping(department_id), 0 , to_char(department_id)  -- to_char로 해서 '전체'를 나오도록한다. to_char를 (그룹여부를묻는)grouping에 묶으면 숫자0이랑 비교를 할수없다. 뒤에 결과값이 나오는 젤뒷부분에 to_char를 붙이자.

                                           , '전체')as 부서번호

       ,count(*) as 인원수          

from employees

group by rollup (department_id); 


--비율 추가

select decode(grouping(department_id), 0 , to_char(department_id)   

                                           , '전체')as 부서번호

       ,count(*) as 인원수

       ,round(count(*)/(select count(*) from employees)*100,1) ||'%' as 비율 

from employees

group by rollup (department_id); 


--부서번호에 전체를 넣기 case문으로

select case grouping(department_id)

              when 0 then to_char(department_id)  

              else '전체' end  as 부서번호

       ,count(*) as 인원수          

from employees

group by rollup (department_id); 


-- 킴벌리의 null을 인턴이라고 바꾸고 비율구하기.

select case grouping(department_id)

              when 0 then nvl(to_char(department_id),'인턴') 

              else '전체' end  as 부서번호

       ,count(*) as 인원수

       ,to_char( round(count(*)/(select count(*) from employees )*100,1),'9990.9' )|| '%' as "비율" --원래는 '999.9'이지만 그렇게하면 정수부가없는것들은 .9 이런식으로나온다 그래서 '9990.9' 0은 정수부가 없으면 0 을써라라는 말임.

from employees

group by rollup (department_id); 


-- 비율부분에 공백을 없애라. ltrim 왼쪽공백자르기 이용.

select case grouping(department_id)

              when 0 then nvl(to_char(department_id),'인턴') 

              else '전체' end  as 부서번호

       ,count(*) as 인원수

       ,ltrim(to_char( round(count(*)/(select count(*) from employees )*100,1),'9990.9' ))|| '%' as "비율" 

from employees

group by rollup (department_id); 




--

--[문제] employess 테이블에서 직종별(job_id) 인원수를 나타내었을때  --------------

--      그 인원수가 10명 이상인 직종별 인원수를 나타내세요.


select job_id

       ,count (*) as 인원수

from employees

-- where count(*) >=10        -- 에러뜸. 어디의 무슨 카운트인지 모름. 

group by job_id

having count(*) >=10;       -- 그룹함수에 대한 조건절.



-- having 을 이용해 그룹에대한 조건을 부여해서 그조건만 출력되도록 한다.

select  department_id as 부서번호

        ,count(*) as 인원수

        ,ltrim(to_char( round(count(*)/(select count(*) from employees )*100,1),'9990.9' ))|| '%' as "비율" 

from employees

group by department_id

having round(count(*)/(select count(*) from employees )*100,1) >= 10 ;  -- 숫자를 비교하니까 숫자타입:숫자타입 으로 맞춰서 조건을 넣는다.



--

select department_id, first_name, salary

from employees

order by department_id asc, salary desc;

 

--[문제]-- 아래처럼 나타내시오

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

연령대      성별     인원수

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

0          남       X명

0          여       X명

10대       남       X명

10대       여       X명

20대       남       X명

20대       여       X명

.........


--[힌트] 나이구하기. => extract(year from sysdate) - ( to_number(substr(jubun,1,2)) + case when substr(jubun,7,1) in('1','2') then 1900 else 2000 end ) +1  => 나이

select V.ageline as 연령대

       ,V.gender as 성별

       ,count(*) as 인원수

from

(

select trunc((extract(year from sysdate) - ( to_number(substr(jubun,1,2)) + case when substr(jubun,7,1) in('1','2') then 1900 else 2000 end ) +1),-1) as ageline

       ,case when substr(jubun, 7, 1) in ('1','3') then '남' else '여' end as gender

from employees

)V

group by V.ageline, V.gender -- 연령대별로 모은다음 다시 성별대로 2차로 그룹을 모음. 

order by 1, 2 ;



--rollup 해서 연령대별 전체가 몇명인지. 보이게하고, grouping으로 그룹인지 아닌지를 판별하고 null값의 이름을 바꾸기. decode

select decode(grouping(V.ageline),0,to_char(V.ageline)

                                     ,'전체')as 연령대

       ,decode(grouping(V.gender),0,V.gender

                                    ,'전체')as 성별

       ,count(*) as 인원수

from

(

select trunc((extract(year from sysdate) - ( to_number(substr(jubun,1,2)) + case when substr(jubun,7,1) in('1','2') then 1900 else 2000 end ) +1),-1) as ageline

       ,case when substr(jubun, 7, 1) in ('1','3') then '남' else '여' end as gender

from employees

)V

group by rollup(V.ageline, V.gender)  

order by 1, 2 ;


-- 롤백보다 좀더 자세히 나오는것 : case 로 하고 비율까지 구하기.

select case grouping(V.ageline) when 0 then to_char(V.ageline)

                                  else '전체' end as "연령대"

       ,case grouping(V.gender) when 0 then V.gender

                                  else '전체' end as "성별"

       ,count(*) as "인원수"

       ,round(count(*)/(select count(*) from employees)*100,1)||'%' as "비율"

from

(

select trunc((extract(year from sysdate) - ( to_number(substr(jubun,1,2)) + case when substr(jubun,7,1) in('1','2') then 1900 else 2000 end ) +1),-1) as ageline

       ,case when substr(jubun, 7, 1) in ('1','3') then '남' else '여' end as gender

from employees

)V

group by rollup(V.ageline, V.gender)  

order by 1, 2 ;


--cube --그룹으로 나눈거의 전체를 다시 나눠주는 것이 생김..

select case grouping(V.ageline) when 0 then to_char(V.ageline)

                                  else '전체' end as "연령대"

       ,case grouping(V.gender) when 0 then V.gender

                                  else '전체' end as "성별"

       ,count(*) as "인원수"

       ,round(count(*)/(select count(*) from employees)*100,1)||'%' as "비율"

from

(

select trunc((extract(year from sysdate) - ( to_number(substr(jubun,1,2)) + case when substr(jubun,7,1) in('1','2') then 1900 else 2000 end ) +1),-1) as ageline

       ,case when substr(jubun, 7, 1) in ('1','3') then '남' else '여' end as gender

from employees

)V

group by cube(V.ageline, V.gender)  

order by 1, 2 ;


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

--

select department_id

       ,decode(department_id,80,1) -- 80번이면 1을주고 아니면 아무것도안줌(null을줌)

from employees;


--

select sum( decode(department_id,80,1) )  --sum은 그룹함수이므로 null값을 빼버리고 계산한다. 

from employees;


select count(*)

from employees

where department_id = 80;  --위와 같은 것임.


--

--[문제] 아래처럼 나오도록 하시오 -----


전체사원수   0대  10대   20대   30대   40대   50대   60대 

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

107        12명  12명  20명   23명   14명   21명    5명 

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


select count(*) as "전체사원수"

--    count(V.ageline)

     ,sum(decode(V.ageline,0,1)) as  " 0대"

     ,sum(decode(V.ageline,10,1)) as "10대"

     ,sum(decode(V.ageline,20,1)) as "20대"

     ,sum(decode(V.ageline,30,1)) as "30대"

     ,sum(decode(V.ageline,40,1)) as "40대"

     ,sum(decode(V.ageline,50,1)) as "50대"

     ,sum(decode(V.ageline,60,1)) as "60대"          

from

(

select 

       trunc( (extract(year from sysdate) - ( to_number(substr(jubun,1,2)) + case when substr(jubun,7,1) in('1','2') then 1900 else 2000 end ) +1),-1 ) as ageline

from employees

)V ;

-- 만드려는 조건에 칼럼이 존재하지않으면 인라인뷰로 만들어서 처리해준다  .



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

--[어려운 문제] 

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

job_id 로만 되어있다. // avg를 써야한다 평균치니까~

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

직급명(job_id)  남자평균급여(수당포함)    여자평균급여(수당포함)    전체평균

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

사원

주임

대리            ex) 8500                 ex) 9000              8750

과장

차장

부장

이사

사장


--1번

select V.job_id as "직급명"

       ,avg(V.salaryavg*V.nam) as 남자수당평균

       ,avg(V.salaryavg*V.wo) as 여자수당평균

       ,avg(V.salaryavg) as 전체평균

from

(

select job_id

       ,nvl(salary + (salary*commission_pct), salary) as salaryavg

       ,case when substr(jubun, 7, 1) in ('1','3') then to_number('1') end as nam

       ,case when substr(jubun, 7, 1) in ('2','4') then to_number('1') end as wo

from employees

)V

group by  V.job_id    

order by 2;


--2번

select V.job_id as "직급명"

       ,avg(decode(V.gender,'남','1')*salaryavg) as 남자평균급여

       ,avg(decode(V.gender,'여','1')*salaryavg) as 여자평균급여

       ,avg(salaryavg) as 전체평균

       

from

(

select job_id

       ,nvl(salary + (salary*commission_pct), salary) as salaryavg

       

       ,case when substr(jubun, 7, 1) in ('1','3') then '남' else '여' end as gender

from employees

)V

group by  V.job_id 

order by 2;


--3번 --강사님의 문제풀이


select V.job_id as "직종ID"

--       ,V.gender

--       ,V.montsal

         ,avg(case V.gender when '남' then V.montsal  end) as "남자평균급여"

         ,avg(case V.gender when '여' then V.montsal  end) as "여자평균급여"

         ,avg(montsal) as "전체평균"

from

(

select job_id

       ,case when substr(jubun, 7, 1) in ('1','3') then '남' else '여' end as gender

       ,nvl(salary + (salary*commission_pct), salary) as montsal

       

from employees

)V

group by V.job_id


--***결과물 확인하기


직종id   남    여    전체

IT_PROG 5700 6000 5760


select avg(nvl(salary + (salary*commission_pct), salary))

from employees

where job_id = 'IT_PROG'



--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 5.17화 

 

 -- ***** 누적에 대해서 알아봅시다 ***** --

 

 create table tbl_panmae

 (panmaedate  date default sysdate

 ,jepumname   varchar2(20)

 ,panmaesu    number);

 

 insert into tbl_panmae values(add_months(sysdate,-2),'새우깡',10); 

 insert into tbl_panmae values(add_months(sysdate,-2)+1,'새우깡',15);

 insert into tbl_panmae values(add_months(sysdate,-2)+2,'감자깡',20);

 insert into tbl_panmae values(add_months(sysdate,-2)+3,'새우깡',10);

 

 insert into tbl_panmae values(add_months(sysdate,-1),'고구마깡',7); 

 insert into tbl_panmae values(add_months(sysdate,-1)+1,'새우깡',8);

 insert into tbl_panmae values(add_months(sysdate,-1)+2,'감자깡',10);

 insert into tbl_panmae values(add_months(sysdate,-1)+3,'감자깡',5);

 

 insert into tbl_panmae values(sysdate-4 ,'허니버터칩',30); 

 insert into tbl_panmae values(sysdate-3 ,'고구마깡',15);

 insert into tbl_panmae values(sysdate-2 ,'고구마깡',10);

 insert into tbl_panmae values(sysdate-1 ,'허니버터칩',20);

 

 insert into tbl_panmae values(sysdate ,'새우깡',10);

 insert into tbl_panmae values(sysdate ,'새우깡',10);

 insert into tbl_panmae values(sysdate ,'감자깡',5);

 insert into tbl_panmae values(sysdate ,'허니버터칩',15);

 insert into tbl_panmae values(sysdate ,'고구마깡',20);

 insert into tbl_panmae values(sysdate ,'감자깡',10);

 

  commit;

 

select *

from tbl_panmae;

 

 

select jepumname

       ,to_char(panmaedate, 'yyyy-mm-dd hh24:mi:ss') as panmaedate

       ,panmaesu

from tbl_panmae;


--새우깡만 본다.

select jepumname

       ,to_char(panmaedate, 'yyyy-mm-dd hh24:mi:ss') as panmaedate

       ,panmaesu

from tbl_panmae

where jepumname='새우깡';

 

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

제품명   판매일자  판매량  

새우깡 2016-03-17 10

새우깡 2016-03-18 15

새우깡 2016-03-20 10

새우깡 2016-04-18 8

새우깡 2016-5-17 10개 

새우깡 2016-5-17 10개

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


--[문제]아래와 같이 구해보자 

제품명 판매월    판매량  

새우깡 2016-03 35

새우깡 2016-04    8

새우깡 2016-05 20


--

select 

       to_char(panmaedate, 'yyyy-mm') as "판매월"

       ,sum(panmaesu) as"판매량"

from tbl_panmae

where jepumname='새우깡'

group by to_char(panmaedate, 'yyyy-mm')

order by 1;


--[문제] 누적판매량을 추가해서 구해보자----------------------------------

제품명 판매월    판매량  누적판매량

새우깡 2016-03 35      35

새우깡 2016-04    8      43

새우깡 2016-05 20      63



--모든제품을 일단 한번보자

select jepumname 

       ,to_char(panmaedate, 'yyyy-mm') as "판매월"

       ,sum(panmaesu) as"판매량"

from tbl_panmae

group by jepumname, to_char(panmaedate, 'yyyy-mm')

order by jepumname;


--새우깡먼저해보자

--누적 sum()over()

select V.panmonth as "판매월"

       ,V.monthqty as "월판매량"

       ,sum(V.monthqty)over(order by V.panmonth) as "월판매누적량" --sum(어떤것을 차곡차곡 누적할것인지 )over(정렬 기준)

from

(

select to_char(panmaedate, 'yyyy-mm') as panmonth --판매월

       ,sum(panmaesu) as monthqty --판매량

from tbl_panmae

where jepumname='새우깡'

group by to_char(panmaedate, 'yyyy-mm')

) V;


--모든것을 해보자.

select V.jepumname as "제품명"

       ,V.panmonth as "판매월"

       ,V.monthqty as "월판매량"

       ,sum(V.monthqty)over(partition by V.jepumname order by V.panmonth) as "월판매누적량" --  sum(어떤것을 차곡차곡 누적할것인지)over(정렬 기준), partition by (어떤것을 기준으로 칸막이를 칠것인지) 

from

(

select jepumname

       ,to_char(panmaedate, 'yyyy-mm') as panmonth --판매월

       ,sum(panmaesu) as monthqty --판매량

from tbl_panmae

group by jepumname, to_char(panmaedate, 'yyyy-mm')  

) V;


--

create or replace view view_panmae   -- view_panmae 를 테이블은 아니지만 테이블처럼 보이게하는것.

as

select V.jepumname as "제품명"

       ,V.panmonth as "판매월"

       ,V.monthqty as "월판매량"

       ,sum(V.monthqty)over(partition by V.jepumname order by V.panmonth) as "월판매누적량" --  sum(어떤것을 차곡차곡 누적할것인지)over(정렬 기준), partition by (어떤것을 기준으로 칸막이를 칠것인지) 

from

(

select jepumname

       ,to_char(panmaedate, 'yyyy-mm') as panmonth --판매월

       ,sum(panmaesu) as monthqty --판매량

from tbl_panmae

group by jepumname, to_char(panmaedate, 'yyyy-mm')  

) V;


-- 만들어진 뷰테이블을 본다.

select *

from view_panmae;


-- 만들어진 view_panmae 을 조건을 걸어 보고싶은것만 본다 

select *

from view_panmae

where 제품명 in ('감자깡','새우깡');



--[문제]---------------------------------------------- employees를 가지고 해보자.

영화명   상영일자   관객수   누적관객수 

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


create table tbl_movie

as

select job_id as moviename

      , hire_date as playdate

      , salary as people      

from employees;



--

select *

from tbl_movie;


create or replace view view_movie

as

select V.moviename as 영화명

       ,V.playdate as 상영일자

       ,V.people as 관객수

       ,sum(V.people)over(partition by V.moviename order by V.playdate) as "누적관객수"

from

(

select moviename 

       ,to_char(playdate, 'yyyy-mm-dd') as playdate

       ,sum(people) as people

from tbl_movie

group by moviename , to_char(playdate, 'yyyy-mm-dd')

)V ;



select *

from view_movie;


select *

from view_movie;

where substr(상영일자,1,4) in ('2006','2007');








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

 --------- *** 서브쿼리 ( sub Query ) *** ---------------

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


 서브쿼리 (sub Query)란?

 select 문 속에 또 다른 select문이 포함되어져 있을때

 포함되어진 select 문을 서브쿼리(sub Query)라고 부른다.


select ....

from ....  --> 메인쿼리(Main Query) == 외부쿼리

where ... in(select ..... 

              from ....)  --> 서브쿼리(sub Query) ==내부쿼리

 

--

---[문제] employees 테이블에서 기본급여가 제일많은 사람의 정보를 

--  사원번호, 사원명, 기본급여를 나타내세요.

 

 --힌트

 from employees

 where salary = (기본급여가 제일큰 salary)

 

 --문제풀이

 select employee_id as 사원번호

        ,first_name||' '||last_name as 사원명

        ,salary as 기본급여

 from employees

 where salary = (select max(salary) from employees);

 

 

--

---[문제]  employees 테이블에서 기본급여가 제일많은 사람과 제일적은 사람의 정보를 

--      사원번호, 사원명, 기본급여를 나타내세요.


 select employee_id as 사원번호

        ,first_name||' '||last_name as 사원명

        ,salary as 기본급여

 from employees

 where salary = (select max(salary) from employees) or  --제일많은사람

        salary = (select min(salary) from employees) ;   --제일적은사람

 



---[문제] employees 테이블에서 부서번호가 60,80번 부서에 근무하는 사원들 중에

-- 월급이 50번 부서 직원들의 '평균월급'보다 많은 사원들만 

-- 부서번호,사원번호,사원명,월급을 나타내세요. 


--1

select department_id as 부서번호

       ,employee_id as 사원번호

       ,first_name||' '||last_name as 사원명

       ,nvl(salary + (salary*commission_pct), salary) as 월급

from employees

where department_id=60 and nvl(salary + (salary*commission_pct), salary) > (select avg(nvl(salary + (salary*commission_pct), salary)) from employees where department_id=50) or

      department_id=80 and (nvl(salary + (salary*commission_pct), salary)) > (select avg(nvl(salary + (salary*commission_pct), salary)) from employees where department_id=50) 

order by 1;


--2

select department_id as 부서번호

       ,employee_id as 사원번호

       ,first_name||' '||last_name as 사원명

       ,nvl(salary + (salary*commission_pct), salary) as 월급

from employees

where department_id in (60,80) and nvl(salary + (salary*commission_pct), salary) > (select avg(nvl(salary + (salary*commission_pct), salary)) from employees where department_id=50) 

order by 1;


--

select avg(nvl(salary + (salary*commission_pct), salary)) as "부서번호50평균월급여"

from employees

where department_id=50;





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

--------------------- ***** pairwise SubQuery ***** ----------------------------

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


--[문제] employees 테이블에서 부서번호별로 기본급이 최대인 사원과

--                                     기본급이 최소인 사원의 정보를 

-- 부서번호, 사원번호, 사원명, 기본급여를 나타내시오.


select department_id

       ,max(salary)  -- 최대

from employees

group by department_id;


select department_id

       ,min(salary)  -- 최소

from employees

group by department_id;


--

from employees

where () -- pairwise SubQuery  컬럼을 2개를 묶어버림. 



--

select department_id as 부서번호

       ,employee_id as 사원번호

       ,first_name||' '||last_name as 사원명

       ,salary as 기본급여

from employees

where (department_id, salary) in (select department_id        ---- pairwise subquery  컬럼을 2개를 묶어버림. 부서번호이면서 기본급여인사람 중 in (부서별로묶고 각각의 부서들 중에서 max기본급여)

                                          ,max(salary) 

                                  from employees

                                  group by department_id)

      or

       (department_id, salary) in (select department_id

                                          ,min(salary) 

                                  from employees

                                  group by department_id)

order by 1, 4 desc;



-- 부서번호가 null인 Kimberely Grant 까지 올려주기 

select department_id as 부서번호

       ,employee_id as 사원번호

       ,first_name||' '||last_name as 사원명

       ,salary as 기본급여

from employees

where (nvl(department_id,-9999), salary) in (select nvl(department_id,-9999)            ---- pairwise subquery  컬럼을 2개를 묶어버림. 부서번호이면서 기본급여인사람 중 in (부서별로묶고 각각의 부서들 중에서 max기본급여)

                                          ,max(salary) 

                                  from employees

                                  group by department_id)

      or

       (nvl(department_id,-9999), salary) in (select nvl(department_id,-9999)

                                          ,min(salary) 

                                  from employees

                                  group by department_id)

order by 1, 4 desc;



--is로 처리하는거

select department_id as 부서번호

       ,employee_id as 사원번호

       ,first_name||' '||last_name as 사원명

       ,salary as 기본급여

from employees

where (department_id, salary) in (select department_id        ---- pairwise subquery  컬럼을 2개를 묶어버림. 부서번호이면서 기본급여인사람 중 in (부서별로묶고 각각의 부서들 중에서 max기본급여)

                                          ,max(salary) 

                                  from employees

                                  group by department_id)

      or

       (department_id, salary) in (select department_id

                                          ,min(salary) 

                                  from employees

                                  group by department_id)

      or department_id is null

order by 1, 4 desc; 






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

--------------------- ***** 상관 SubQuery (==서브상관쿼리) ***** ----------------------------

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

[ 상관 SubQuery ] 이라 함은 Main Query(==외부쿼리) 에서 사용된 

테이블에 존재하는 컬럼이 Sub Query(==내부쿼리)의 조건절( where절 , having 절 )에

사용되어질때를 말한다 


select department_id

       ,employee_id

       ,salary                                                                                                                                       --이 라인이 외부쿼리 테이블에 존재하는 컬럼

       ,( select count(*)+1 from employees where salary > E.salary ) as "기본급여등수1" -- +1은 등수를 구하니까. 이런식으로 구하면 어느 DB건 호환할수있다. --이 라인이 내부(서브)쿼리 에 사용되는것이 상관서브쿼리

       ,rank()over(order by salary desc) as "기본급여등수2"                             -- rank는 오라클이 제공해주는 함수이다. 제한적이다.

       ,rank()over(partition by department_id order by salary desc) as "부서내기본급여등수1" 

       ,( select count(*)+1 from employees where department_id =  E.department_id and  salary > E.salary  ) as "부서내기본급여등수2" -- 내 department_id가 E.department_id and  salary(나의기본급여) > E.salary

from employees E

order by 1,3 desc;




select employee_id

       ,salary

       ,sum(salary)over(order by employee_id) as"누적1"

       

       ,( select sum(salary)

          from employees 

          where employee_id <= E.employee_id ) as "누적2"

from employees E

order by employee_id


--

select V.moviename as 영화명

       ,V.playdate as 상영일자

       ,V.people as 관객수

       ,sum(V.people)over(partition by V.moviename order by V.playdate) as "누적관객수1"

       ,(select sum(people)

       from tbl_movie

       where moviename = V.moviename and playdate <= V.playdate) as "누적관객수2"

from

(

select moviename 

       ,to_char(playdate, 'yyyy-mm-dd') as playdate

       ,sum(people) as people

from tbl_movie

group by moviename , to_char(playdate, 'yyyy-mm-dd')

)V ;


--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 5.18


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

------------------************** 상관 서브쿼리를 통한 update 문 처리 **************------------------

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


create table tbl_bjh_emp

as

select * from employees;



select *

from tbl_bjh_emp;


update tbl_bjh_emp set first_name='배재현'

where employee_id = 100;


commit;



--

-- 컴퓨터속성 -> 이름바꾸고 다시 시작하면 오류가난다.  C:\oraclexe\app\oracle\product\11.2.0\server\network\ADMIN 경로에 간다. 그다음 리스너켜서 호스트부분과 일치시켜준다. ,또 tnsnames 켜서 호스트부분도 일치시켜준다

            --또 , 명령프롬프트 키고 lsnrctl start 하고 엔터, (안되면 제어판: 제어판\모든 제어판 항목\관리 도구 서비스 오라클 XETN리스너 시작시켜줌 그다음 재부팅한다. )


--XE*(이름바꿔준다)* =  <- 이부분이 네트서비스명 

--  (DESCRIPTION =

--    (ADDRESS = (PROTOCOL = TCP)(HOST = user2-PC12*(연결할컴퓨터명으로바꿔준다)*)(PORT = 1521))                    --원래 호스트에는 아이피를 씀

--    (CONNECT_DATA =

--      (SERVER = DEDICATED)

--      (SERVICE_NAME = XE)

--    )

--  )


--제어판\모든 제어판 항목\Windows 방화벽 -> 고급설정 -> 인바운드 -> 새규칙 -> 포트 -> 특정포트입력-> 만들기.

-->확인하기 cmd-> tnsping ->



------ *** 데이터베이스 링크 생성하기 *** ----- 


--상대방오라클에가자 링크생성

create database link link12

connect to hr identified by hr       --상대방 hr임 뒤 hr은 암호.

using 'EX12';   --이렇게하면 Database link LINK12이(가) 생성되었습니다.


--생성된 데이터베이스 링크 조회하자

select *

from user_db_links;


--연결해보자 남의 테이블보기

select *

from tbl_ojs_emp@link12; -- 골뱅이를 쓰고 생성한 접근하고픈 링크에 간다.


select *

from employees@link12; -- 골뱅이를 써야 남에것이 나옴.


----자기테이블보기 실수후 처리방법..

select *

from tbl_bjh_emp;


--실수함

update tbl_bjh_emp set last_name ='왕'; 

--실수함... last_name 부분이 모두 왕이됨.. commit해서 롤백도안됨;

commit;



--상대방 employees last_name 부분을 덮어씌어보자

select *

from employees@link12;


--상대방것을 서브쿼리를 이용해서 바꿔보자

update tbl_bjh_emp ME set last_name = ( select last_name                       --상대방것으로 내것을 바꿀 정보를 set last_name 에다가 정보를바꿔서 넣어 보여줌.

                                        from employees@link12

                                        where employee_id = ME.employee_id )   --서브쿼리를 이용 조건을 맞춰줘서 반복문처럼 하나하나 비교하면서 넣어줌.

                                        

commit;





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

    ------------- ************** JOIN (조인) ************** ---------------- 중요!

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

join(조인)은 테이블(뷰)과 테이블(뷰)를 합치는 것을 말하는데,

행(row)를 합치는 것이 아니라,

컬럼(column)과 컬럼(column)을 합치는것이다.

그리고, 서로 다른 테이블(뷰)의 행(row)과 행(row)을 합치는 것은 UNION 연산자를 사용하는 것이다. 



A = {1,2,3} 원소가 3개

B = {a,b}   원소가 2개


A⊙B = {(1,a),(1,b)

       ,(2,a),(2,b)

       ,(3,a),(3,b)}

       데카르트 곱

       데카르트 곱(수학) => 원소의 곱 : 3*2 = 6개 (모든 경우의 수)

짝을 맺을수있는 가지수는 6가지.


--> 데카르트곱을 데이터베이스에서는 Catersian Product (모든 경우의 수) 라고 부른다.

select *

from employees;


select count(*) --107개

from employees; 


select count(*) --27개

from departments;


select count(*) --2889 (107*27) Catersian Product (모든 경우의 수)

from employees,departments; 


--------- JOIN : SQL 1992 CODE 방식 (데이터베이스 벤더(회사)마다 문법이 다름)

--               SQL 1999 CODE 방식 (ANSI SQL 표준화)  => 이것을 쓰기를 권장함



--1.SQL 1992 CODE 방식 ==> 테이블(뷰)과 테이블(뷰) 사이에 조인시 콤마(,)를 찍어주는 것.


--2.SQL 1999 CODE 방식 (ANSI SQL 표준화) ==> 테이블(뷰)과 테이블(뷰) 사이에 조인시 join 이라는 단어를 넣어주는 것. 


--방식1

select *

from employees,departments; --  Catersian Product (모든 경우의 수)


--방식2

select *

from employees cross join departments; --  Catersian Product (모든 경우의 수) 모든경우일때는 join 앞에 cross를 넣어준다.


--

select count(*)

from employees,departments; -- 2899

select count(*)

from employees cross join departments; --2899 


--방식1

select *

from employees E , departments D

where E.department_id = D.department_id; --조인조건절 

-- equi join (=)


--방식2

select *

from employees E inner join departments D   --조건절에 일치하는것만 보려면 inner 라고 쓴다.

on E.department_id = D.department_id;         -- 조인조건절이 1999방식에선 on 이라고 쓴다.

-- inner join (내부조인)


--방식2-1

select *

from employees E join departments D   

on E.department_id = D.department_id ;

-- inner는 생략가능 하다.


-- null 인놈은 안나왔다. 킴벨리를 나오도록해보자.

--방식1( 1992 )

select *

from employees E , departments D   

where E.department_id = D.department_id(+) ; -- (+) 가 없는 employees E 의 모든행을 출력하고 부서번호가 그다음 조건 E.department_id = D.department_id 로 짝지어라 라는말.   (+)를 붙이면 null값도 나옴.

--방식1-2( 1992 )

select *

from employees E , departments D   

where E.department_id(+) = D.department_id ; -- (+) 가 없는 departments D 의 모든행을 출력하고 그다음 조건 E.department_id = D.department_id 로 짝지어라 라는말.  킴벌리의 null값은 안나옴 


--방식2 ( 1999 )

select *

from employees E () join departments D  --> () 에 left right full 이 들어갈수있다.  



from employees E left join departments D  --> 왼쪽을 테이블을 보여라  

from employees E right join departments D -->오른쪽을 테이블을 보여라

from employees E full join departments D --> 모든테이블을 일단 보여라.

-- 요 3개를 outer join(외부조인) 이라하고 outer는 생략이 가능하다.


--1 ( 1999 )

select *

from employees E left join departments D

on E.department_id = D.department_id;  --킴벨리나옴


--2 ( 1999 )

select *

from employees E right join departments D

on E.department_id = D.department_id;     --킴벨리는 부서가없기때문에 안나옴.


--3 ( 1999 )

select *

from employees E full join departments D

on E.department_id = D.department_id;    --킴벨리도 나오고 사람없는 부서도 다나옴.


--4( 1999 ) 아우터 생략

select *

from employees E join departments D

on E.department_id = D.department_id;  

-- 기본 이너조인에서 left , right, full 을 쓰느냐에 따라서 달라짐 기본이너조인은 조건절 on 에맞는것만 나오게함.


----

select employee_id

       ,first_name||' '||last_name

       ,department_name

       ,department_id -- 요부분 실행이 안됨... -- 얘는 employees,departments 이랑 둘다 갖고있는 성분이 아니라서 오류가남

from employees E join departments D

on E.department_id = D.department_id;


----

select employee_id

       ,first_name||' '||last_name

       ,department_name

       ,E.department_id     -- E를 붙여주면 가능함.

from employees E join departments D

on E.department_id = D.department_id;


----

select E.employee_id as 사원번호                      -- E나 D를 붙여주면 속도가 높아짐 왜냐하면 다뒤지는거에 비해서 있는곳에서 뒤지기때문에.. 불편해도 이렇게하자. 

       ,E.first_name||' '||last_name as 사원명

       ,D.department_name as 부서명

       ,E.department_id as 부서번호

from employees E join departments D

on E.department_id = D.department_id;


---- null 값까지 나오게하려면..

select E.employee_id as 사원번호                      

       ,E.first_name||' '||last_name as 사원명

       ,D.department_name as 부서명

       ,E.department_id as 부서번호

from employees E left join departments D   -- 킴벌리 까지 나오게함.

on E.department_id = D.department_id;



--[문제]-------------

부서명      인원수

-------------------- 부서명 별로 이름을 구하시오 . + 전체사원과 비율을 구하시오


--문제풀이 

부서명 - departments 테이블에 있다.

인원수 - employees 테이블에 있다.

두개를 합쳐야함. 조인해서.


select nvl(D.department_name,'인턴') as "부서명"

       ,count(*) as "인원수"

from employees E left join departments D

on E.department_id = D.department_id

group by D.department_name 

order by 1;


--  + 전체사원과 비율을 구하시오

select decode(grouping(D.department_name), 0 , nvl(D.department_name,'인턴')

                                               , '전체') as "부서명"

       ,count(*) as "인원수"

       ,round(count(*)/(select count(*) from employees)*100,1) ||'%' as 비율

from employees E left join departments D

on E.department_id = D.department_id

group by rollup(D.department_name) 

order by 1;




--[문제]------------------------------------------------------

사원번호 사원명 월급 전체사원평균월급 평균차액(월급-전체사원평균월급)

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


--정답풀이

select A.employee_id as 사원번호

       ,A.first_name||' '||last_name as 사원명

       ,nvl(A.salary + (A.salary*A.commission_pct), A.salary) as 월급

       ,E.avgsal as 전체사원평균월급

       ,nvl(A.salary + (A.salary*A.commission_pct), A.salary) - E.avgsal as 평균차액

from employees A cross join (select trunc(avg(nvl(salary + (salary*commission_pct), salary))) as avgsal from employees ) E

order by 1;


cross -- 모든경우의수 

select trunc(avg(nvl(salary + (salary*commission_pct), salary))) as avgsal from employees -- 오로지 1개가 나옴..  employees A(107개) * E(1개) = 107개




-- + 지표(평균보다 몇배 더버는지)

-- 7150(평균월급) : 100 = 24000(월급) : x

-- 7150 : 100 = 9000 : x

-- X = 24000(월급) * 100 / 7150(평균월급) - 지표공식

 

select A.employee_id as 사원번호

       ,A.first_name||' '||last_name as 사원명

       ,nvl(A.salary + (A.salary*A.commission_pct), A.salary) as 월급

       ,E.avgsal as 전체사원평균월급

       ,nvl(A.salary + (A.salary*A.commission_pct), A.salary) - E.avgsal as 평균차액

       ,trunc((nvl(A.salary + (A.salary*A.commission_pct), A.salary)*100)/E.avgsal) as 지표 -- X = 24000(월급) * 100 / 7150(평균월급)

from employees A cross join (select trunc(avg(nvl(salary + (salary*commission_pct), salary))) as avgsal from employees ) E

order by 6 desc;



--[문제]-----------------------------------------------------------------

부서번호 사원번호 사원명 월급 부서별평균월급 평균차액(월급-부서별평균월급) 지표

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

 

 

--문제풀이

select A.department_id as 부서번호

       ,A.employee_id as 사원번호

       ,A.first_name||' ' ||last_name as 사원명

       ,nvl(A.salary + (A.salary*A.commission_pct), A.salary) as 월급

       ,trunc(B.avgsal) as 부서별평균월급

       ,trunc(nvl(A.salary + (A.salary*A.commission_pct), A.salary) - B.avgsal) as 평균차액

       ,trunc((nvl(A.salary + (A.salary*A.commission_pct), A.salary) * 100) / B.avgsal ) as 지표 -- X(지표) = 24000(월급) * 100 / 7150(평균월급) - 지표공식

from employees A left join (select nvl(department_id,-999) as department_id -- department_id 라고 as를 해줘야한다. B.department_id 로 접근해야하니까

                                     ,avg(nvl(salary + (salary*commission_pct), salary)) as avgsal

                               from employees 

                               group by department_id order by 1) B

on nvl(A.department_id,-999) = B.department_id

order by 1, 7 desc;





--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 5.19



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

    ------------- ************** Non Equi-JOIN ************** ---------------- 

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


Non Equi-JOIN --> 어떤 컬럼의 값이 특정 범위에 속할 때 사용하는 JOIN이다 . 범위에만 들어가는것이지 정확하게 일치하지 않음.


-- 소득세율 지표관련 테이블을 생성한다.

create table tbl_taxindex

(taxpercent   number -- 세율 2%,5%,8%,10% .... 세금%

,lowincome    number -- 연봉의 최저범위

,highincome   number -- 연봉의 최고범위

);


insert into tbl_taxindex values(0.02,1,99999);

insert into tbl_taxindex values(0.05,100000,149999);

insert into tbl_taxindex values(0.08,150000,199999);

insert into tbl_taxindex values(0.1,200000,10000000000000000);


commit;


select *

from tbl_taxindex;



--각사원마다 연봉으로 세금을 얼마때는지 알아보자.

select employee_id

       ,first_name||' '||last_name as ename

       ,nvl(salary + ( salary * commission_pct), salary) *12 as yearincome 

from employees;



--1992 방식

select A.employee_id as 사원번호

       ,A.ename as 사원명

       ,A.yearincome as 연봉

       ,B.taxpercent*100 ||'%' as 소득세율  --0.02 이런식으로 보여주기 싫으니까 100곱하고 %를 붙여주자.

       ,to_char(trunc (A.yearincome * B.taxpercent),'L999,999') as 연소득세액  -- 보기좋게 보여주도록한다. 

from

(

select employee_id

       ,first_name||' '||last_name as ename

       ,nvl(salary + ( salary * commission_pct), salary) *12 as yearincome 

from employees

) A , tbl_taxindex B

where A.yearincome between B.lowincome and B.highincome; -- between 을써서 비교할것을 앞에 쓰고 범위를 (a범위) between (b범위) 에 넣어준다. case 문을써도 되지만 case문은 값이 편동되지않는것에 쓰는게 좋다.



--1999 방식 

select A.employee_id as 사원번호

       ,A.ename as 사원명

       ,A.yearincome as 연봉

       ,B.taxpercent*100 ||'%' as 소득세율  --0.02 이런식으로 보여주기 싫으니까 100곱하고 %를 붙여주자.

       ,to_char(trunc (A.yearincome * B.taxpercent),'L999,999') as 연소득세액  -- 보기좋게 보여주도록한다. 

from

(

select employee_id

       ,first_name||' '||last_name as ename

       ,nvl(salary + ( salary * commission_pct), salary) *12 as yearincome 

from employees

) A join tbl_taxindex B

on A.yearincome between B.lowincome and B.highincome;



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

    ------------- ************** 자기조인 (Self Join) ************** ---------------- 

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


--[문제]-------------------------------------------------------------------------

부서번호        사원번호        사원명       입사일자     직속상관번호 직속상관명

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

department_id  employee_id   first_name   hire_date    manager_id    first_name  

                             last_ name               employee_id   last_ name               --직속상관명과 사원명의 컬럼은 같지만 다르게 표현해야한다.

                            

                            

select *

from employees;



--1992 방식


select E1.department_id as 부서번호

       ,E1.employee_id as 사원번호

       ,E1.first_name||' '|| E1.last_name as 사원명

       ,to_char(E1.hire_date,'yyyy-mm-dd') as 입사일자

       ,E2.employee_id as 직속상관번호

       ,E2.first_name||' '|| E2.last_name as 직속상관명

from employees E1 , employees E2       -- ( 자기가 자기한테 같은 테이블을 셀프조인함 단, as 만 다르게한다)

where E1.manager_id = E2.employee_id(+)  -- 직속상관 id 와 직속상관의 부서번호id가 일치하는놈만 나와라 라는말. -- king 은 직속상관이없다

order by 1,2;


--1999 방식

select E1.department_id as 부서번호

       ,E1.employee_id as 사원번호

       ,E1.first_name||' '|| E1.last_name as 사원명

       ,to_char(E1.hire_date,'yyyy-mm-dd') as 입사일자

       ,E2.employee_id as 직속상관번호

       ,E2.first_name||' '|| E1.last_name as 직속상관명

from employees E1 left join employees E2       -- ( 자기가 자기한테 같은 테이블을 셀프조인함 단, as 만 다르게한다)

on E1.manager_id = E2.employee_id  -- 직속상관 id 와 직속상관의 부서번호id가 일치하는놈만 나와라 라는말. -- king 은 직속상관이없다

order by 1,2;




--책에대한 테이블만들고 예제를 해보자--------------------

create table tbl_authorbook

(bookname   varchar2(100)

,authorname varchar2(20)

,loyalty    number(5)

);


insert into tbl_authorbook values('오라클','송성학',1000);

insert into tbl_authorbook values('오라클','강지혜',1500);


insert into tbl_authorbook values('해리포터','송성학',2000);

insert into tbl_authorbook values('상실의시대','공현정',3000);

insert into tbl_authorbook values('연금술사','김수현',1000);


insert into tbl_authorbook values('개미','전해정',2000);

insert into tbl_authorbook values('개미','김수현',1700);


commit;


select *

from tbl_authorbook;



--[문제]-tbl_authorbook 테이블에서 공저(같이지음)로 지어진 도서정보만 출력하세요.

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

도서명 작가명 로얄티

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

오라클 송성학 1000

오라클 강지혜 1500

개미 전해정 2000

개미 김수현 1700


--1 셀프조인

select A1.bookname as 책이름

       ,A1.authorname as 작가명

       ,A1.loyalty as 로얄티

from tbl_authorbook A1 join tbl_authorbook A2

on A1.bookname = A2.bookname and A1.authorname != A2.authorname; --책이름은 같지만 작가이름이 달라야한다.


--2 group by

select bookname,count(*)

from tbl_authorbook

group by bookname


select *

from tbl_authorbook

where bookname in ( select bookname

                    from tbl_authorbook

                    group by bookname

                    having count(*) > 1 ); -- 카운트되는 갯수로 그룹의 조건절인 having 을써서 구함.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@5.20 추가내용 

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

    ------------- ************** multi table join (다중 테이블 조인) ************** ---------------- 

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

multi table join (다중 테이블 조인) -> 3개이상의 테이블을 가지고 조인스켜주는 것이다.


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

  부서번호   부서명   사원번호  사원명   연봉   세율

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

    D         D        E      E      E      T


departmnets  : D 

employees    : E

tbl_taxindex : T


-- 일단 두개를 가지고 조인을한다.

select *

from employees E left join departments D

on E.department_id = D.department_id;       


-- 위 전체를 테이블로보고 다시 조인함  /  다중조인 D E T 모두 조인하는법. 

select E.department_id as 부서번호

       ,D.department_name as 부서명

       ,E.employee_id as 사원번호

       ,E.first_name||' '||E.last_name as 사원명

       ,nvl(E.salary+(E.salary*E.commission_pct), E.salary)*12 as 연봉

       ,T.taxpercent as 세율

       ,(nvl(E.salary+(E.salary*E.commission_pct), E.salary)*12 * T.taxpercent) as 연소득세

from employees E left join departments D

on E.department_id = D.department_id 

join tbl_taxindex T

on nvl(E.salary+(E.salary*E.commission_pct), E.salary)*12 between T.lowincome and T.highincome ; --이런식으로 다중으로 조인시킨다.



--[문제] ------------------------------------------------------이렇게 나오게하시오.

부서번호 부서명 도시명 사원번호 사원명 기본급여 

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

select * from employees;

select * from departments;

select* from locations; -- 각각 중복되는 내용이 뭔지 보고 잘 이어주면 쉽게할수있다.



select E.department_id as 부서번호

       ,D.department_name as 부서명

       ,L.location_id as 도시명

       ,E.employee_id as 사원번호

       ,E.first_name||' '||E.last_name as 사원명 

       ,E.salary as 기본급여

from employees E left join departments D

on E.department_id = D.department_id

left join locations L

on L.location_id = D.location_id;



@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@5.20  유니온설명 위에 위치

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

    ------------- ************** UNION / UNION ALL / INTERSECT / MINUS ************** ---------------- 

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


1.UNION 은 테이블(뷰)과 테이블(뷰) 을 합쳐서 보여주는데 

  이것은 행과 행을 합친 결과를 보여주는 것이다.

  

select *

from tbl_panmae;



--[문제] tbl_panmae 테이블에서 이번달에 판매한것만 추출하세요.


--이번달

select *

from tbl_panmae

where to_char(panmaedate,'yyyy-mm') = to_char(sysdate,'yyyy-mm');


--3월달

create table tbl_panmae_201603  -- 예전꺼는 따로 빼서 저장해놓음.

as

select *

from tbl_panmae

where to_char(panmaedate,'yyyy-mm') = '2016-03';


--4월달

create table tbl_panmae_201604 --예전꺼는 따로 빼서 저장

as

select *

from tbl_panmae

where to_char(panmaedate,'yyyy-mm') = '2016-04';



-- tbl_panmae 테이블에서 이번달 판매한 것만 놔두고 나머지는 삭제한다. -- 최신것만 tbl_panmae에 넣겠다.

delete from tbl_panmae

where to_char(panmaedate,'yyyy-mm')!=to_char(sysdate,'yyyy-mm');


commit;


select *

from tbl_panmae




--[문제] 2016년 3월 부터~ 2016년 현재월(5월)까지 제품별 월별 판매량의 합을 출력하세요

--3,4월은 우리가 위에서 이미 삭제했다. 다시 행과행을 합쳐서 만들어보자.


select *

from tbl_panmae_201603

union

select *

from tbl_panmae_201604

union

select *

from tbl_panmae;


-- 문제풀이. 유니온으로 하면 합쳐짐. -- union  합집합에 중복포함되는 내용은 중복안되게 다 보여줌. (자동으로 소트됨)


select jepumname as 제품명

       ,to_char(panmaedate,'yyyy-mm') 판매월

       ,sum(panmaesu) as 판매량

from 

(

select *

from tbl_panmae_201603

union

select *

from tbl_panmae_201604

union

select *

from tbl_panmae

) V

group by jepumname, to_char(panmaedate,'yyyy-mm')

order by 1,2 ; 



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

--------------------------------- union all


select *

from tbl_panmae_201603;


insert into tbl_panmae 

select *

from tbl_panmae_201603

where jepumname='감자깡'; --3 월달에 판매되어진 감자깡을 tbl_panmae에 넣으시오 라는말.


select *

from tbl_panmae_201604;


insert into tbl_panmae 

select *

from tbl_panmae_201604

where jepumname='새우깡' --4 월달에 판매되어진 새우깡을 tbl_panmae에 넣으시오 라는말.


commit;


select *

from tbl_panmae ;


-- union all  합집합에 포함되는 중복된내용도 전부 다 보여줌. (확실하게 중복된 사항이 없다고하면 union 보다는  union all이 속도가 더빠르니 union all을 쓰자)


select *

from tbl_panmae_201603

union all

select *

from tbl_panmae_201604

union all

select *

from tbl_panmae ;


--위치를 바꿔보자 


select *

from tbl_panmae_201603

union all

select *

from tbl_panmae 

union all

select *

from tbl_panmae_201604 ;





----------------------------------------INTERSECT / MINUS 

INTERSECT - 합집합부분(중복된부분)만 나오게해줌. 

MINUS - 차집합부분만(중복된부분빼고 나머지부분만) 나오게해줌.


--INTERSECT

select *

from tbl_panmae_201603

intersect --둘다 갖고있는것을 뽑아서 보여줌.

select *

from tbl_panmae;


--MINUS

select *

from tbl_panmae_201604 

minus   --위에 테이블을 기준으로 중복된것을 빼고 보여줌

select *

from tbl_panmae;


--MINUS

select *

from tbl_panmae

minus  --위에 테이블을 기준으로 중복된것을 빼고 보여줌

select *

from tbl_panmae_201604;







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

    ------------- ************** 계층형 쿼리 ************** ----------------  답변형 게시판을 만들때 쓰기좋다.

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

  

                                      강지혜

                                        |

                                 |             |

                              송성학          공현정

                              |   |            |

                            수지  최재우       최재이

                                

                                  <계층 구조>         


select *

from employees;


--내 아래라인을 보고싶다 . 이부분 실행시켜보고 결과로 이해하자.

select *

from employees

start with employee_id = 100  --100번부터 출발한다 / 처음에만 100번이고 그다음값은 101이 온다 반복문같다.

connect by prior employee_id = manager_id; --*[prior 다음에 나오는 컬럼명은 start 하는 그 행에 있는 컬럼의 값] 이라고 기억하자 *  /  manager_id의 컬럼은 start의 컬럼이 아닌 다른행에있는 아이디를 찾는다.

                      --100    = manager_id 가 100인 행을 찾는다.

                      --101    = manager_id 가 101인 행을 찾는다.



                      ex)             강지혜 100

                                        |

                                 |             |

                              송성학 101      공현정 102

                              |      |            |

                         수지 103  최재우 104    최재이 105

                                

                                  <계층 구조>         쭈욱 찾아주고 최하위에서 끝남


-- 내 윗라인을 보고싶다

select *

from employees

start with employee_id = 105 -- 105=>103=>102=>100

connect by prior manager_id = employee_id ;  -- start 하는 105번에 해당하는 manager_id를 먼저씀 prior뒤에 .  

                      --103   =  103

                      --102   =  102

                      --100   =  100

                      --null 끝

                      

--계층형 쿼리에만 쓰이는 level 이있다.

select level -- 내밑으로 다 나와 

       ,employee_id as 사원번호

       ,first_name||' '||last_name as 사원명

from employees

start with employee_id = 100 

connect by prior employee_id = manager_id ;



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

100 J king --1레벨

     101 Neena Kochhar --2레벨

          108 Nancy Greenberg --3레벨

               109 Daniel Faviet --4레벨

               110 John Chen

               111 Ismael Sciarra

               112 Jose Manuel Urman

               113 Luis Popp

          200 Jennifer Whalen --3레벨

          203 Susan Mavris

          204 Hermann Baer

          205 Shelley Higgins

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


-- level 이 보기쉽게 들여쓰기를 입힌다


select --level

       lpad(' ', (level-1)*5,' ') || employee_id ||' '|| first_name||' '||last_name as 사원명-- (level-1)*5 만큼 공간을 확보하고, || 을 사용해 붙여줘야 이름전체가 붙으면서 레벨이 뛰어짐

from employees

start with employee_id = 100 

connect by prior employee_id = manager_id ;





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

    ------------- ************** 시퀀스 (Sequence) ************** ----------------## 웹에서 대부분 엄청나게 많이쓴다 **!!! ##  게시판같은거할때 

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


시퀀스 (Sequence) -> 숫자를 자동으로 증가시켜주는 것이다.


create table tbl_gesipan

(writeno  number

,title varchar2(200)

,content varchar2(4000)

,writeday date default sysdate

);




create sequence seq_writeno

start with 1 --나는 1번부터 들어갑니다 라는뜻

increment by 1 -- 증가치(1) 

nomaxvalue -- 들어오는 족족 계속 증가 (맥시멈은없다)

nominvalue -- (미니멈도없다)

nocycle -- cycle하지 않겠다 . cycle을 설정을 1000이라 설정해놓으면 다끝나면 다시 1부터~1000, 다시 1~1000 반복. 

nocache;



-- create sequence seq_writeno ; 위에 설정해둔것과 같다


insert into tbl_gesipan values(seq_writeno.nextval,'집에가고싶다!!','집에 보내주세요~~ 제발요~~~~',default);  --  ' ' 여기에 사용자가 입력한 글이 들어온다.

insert into tbl_gesipan values(seq_writeno.nextval,'자고싶다!!','집에서 자게 해주세요~~ 제발요~~~~',default) ;

insert into tbl_gesipan values(seq_writeno.nextval,'먹고싶다!!','삼겹살도 좋고 떡볶이도 좋고 밥도 좋고 ',default) ;


commit;


select *

from tbl_gesipan


--2번글을 지웠다

delete from tbl_gesipan

where writeno = 2;


commit;


--다른것을 넣었다

insert into tbl_gesipan values(seq_writeno.nextval,'안녕하세요? 한석규 입니다.','좋은 하루되세요~~',default) ;


select *

from tbl_gesipan; --방금넣은것은 4번이되었다.


--또 넣는다.

insert into tbl_gesipan values(seq_writeno.nextval,'안녕하세요? 두석규 입니다.','좋은좋은 하루되세요~~',default) ;

insert into tbl_gesipan values(seq_writeno.nextval,'안녕하세요? 세석규 입니다.','좋은좋은좋은 하루되세요~~',default) ;

insert into tbl_gesipan values(seq_writeno.nextval,'안녕하세요? 네석규 입니다.','좋은좋은좋은좋은 하루되세요~~',default) ;


commit;


select *

from tbl_gesipan

order by 1;


-- 또 지운다 5번글을

delete from tbl_gesipan

where writeno = 5;


commit;


--또 넣는다

insert into tbl_gesipan values(seq_writeno.nextval,'안녕하세요? 오석규 입니다.','오~~좋은 하루되세요~~',default) ;

insert into tbl_gesipan values(seq_writeno.nextval,'안녕하세요? 육석규 입니다.','육성재 친구입니다. 하루되세요~~',default) ;


commit;



select *

from tbl_gesipan

order by 1; --전체가 7개이다 2개를 삭제했으니. 더보기기능을 입혀보자. 시퀀스번호로는 사용할수없다. 삭제된글이 있기때문에. 그래서 행의 개수를 쓴다. rownum, row_number을 사용해서




-- 

select writeno

       ,title

       ,writeday

from

(

select row_number()over(order by writeno) as rno -- row nomber 

       ,writeno

       ,title

       ,writeday

from tbl_gesipan

order by 1

) V -- 인라인뷰를 이용해  rno 를 컬럼화 한다.

where rno between 1 and 3 ; --3개씩 보여줘라 


--더보기를 누르면 

where rno between 1 and 3  이것이 where rno between 4 and 6 으로 바뀌고 계속 더보기를 누르면 3의 배수로 증가하다가 끝이남.


-- 시퀀스는 고유한 값을 넣을때 자동으로 증가시켜준다. 삭제를 시키면 빵구가 일어나기 때문에 더보기기능은 row_number로 설정해서 쓴다. 








--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 5.19

밑에꺼는 내일 이어서할거임

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

    ------------- ************** 테이블을 만들때************** ---------------- 

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


--constraint-> 제약조건


      --부모 테이블 1    * 부모와 자식은 [ 1 : 多 ] 관계라고하고 이렇게 되어진것을 제1정규화를 한 결과이다. 

create table tbl_buseo

(buno number(3) not null -- 이미 밑에서 프라이머리키설정해주어서 안써도되지만 not null을 써주는것이 좋다.

,buname varchar2(20) not null --null은 들어올수없다

,addr Nvarchar2(100) -- not null을 안쓰면 널을 쓸수있다.


,constraint PK_tbl_buseo_buno primary key(buno)  --constraint PK_테이블명_프라이머리키로할컬럼 으로 한다.  프라이머리키는 null값이 들어올수없다.또한 중복된 ID는 허락하지 않는 것.

);


      --자식 테이블 多(Many)

create table tbl_sawon

(

sawonno number(4) not null 

,saname Nvarchar2(20) not null

,jubun  varchar2(13) not null

--,hakbun varchar2(20) not null

,jik    Nvarchar2(10) default '사원'-- 값을 안넣어주면 '사원'으로 자동으로됨

,hiredate date default sysdate-- 값을 안넣어주면 sysdate 현재시각 . default는 안넣어주면 이라는 것이라 생각하자.

,buno number(3)


,constraint PK_tbl_sawon_sawonno primary key(sawonno) 

--,constraint PK_tbl_sawon_jubun primary key(jubun) --오류(table can have only one primary key) 프라이머리키는 오로지 테이블당 1개밖에 안된다.

,constraint UQ_tbl_sawon_jubun unique(jubun) --그래서 UQ를 unique 쓴다.UQ는 여러개 들어와도된다.

--,constraint UQ_tbl_sawon_hakbun unique(hakbun)  --unique 여러개써도됨

,constraint CK_tbl_sawon_jik check(jik in('사장','부장','과장','대리','사원')) --CK check는 들어올 내용을 검사해서 어느칼럼의 in() in의 괄호 안에있는것만 들어와야한다는 조건을 거는것.

,constraint FK_tbl_sawon_buno foreign key(buno) references tbl_buseo(buno) -- FK foreign key 외부에있는것을 references (테이블명(칼럼)) 의 형식을 써주고 테이블명의 칼럼을 참조하겠다는 말 (참조받는테이블이 먼저 존재해야함)

);


insert into tbl_buseo values(10,'연구부','서울');

insert into tbl_buseo values(20,'관리부','부산'); 

insert into tbl_buseo values(30,'생산부','대구');

insert into tbl_buseo values(40,'영업부','광주');


insert into tbl_sawon values(1001,'일미자','8010012234567','사장', default, 20);

insert into tbl_sawon values(1002,'이미자','8110012234567','부장', default, 10);

insert into tbl_sawon values(1003,'삼미자','8210012234567','과장', default, 10);

insert into tbl_sawon values(1004,'사미자','8310012234567','대리', default, 10);

insert into tbl_sawon values(1005,'오미자','8410012234567','사원', default, 10);


commit;


select *

from tbl_buseo;


select *

from tbl_sawon;


drop table tbl_sawon purge; --테이블삭제방법




------- *** 컬럼명 변경하기 *** -----------------

select *

from tbl_sawon;



alter table tbl_sawon rename column jubun to juminno; --alter table (바꿀테이블) rename column (현재컬럼명) to (새로운컬럼명);


alter table tbl_sawon rename column juminno to jubun; --원상복구.



------- *** 테이블명 변경하기 *** -----------------


rename tbl_sawon to tbl_jikwon; --rename (현재테이블명) to (바꿀테이블명) ;


select *

from tbl_jikwon;


rename tbl_jikwon to tbl_sawon; --원상복구


select *

from tbl_sawon;



------- *** 컬럼의 데이터타입 변경하기 *** -----------------


desc tbl_sawon; --테이블에 데이터타입검색하는것.


alter table tbl_sawon modify saname Nvarchar2(30); --alter table (테이블명) modify (변경해야할컬럼명) (변경할데이터유형)


alter table tbl_sawon modify saname Nvarchar2(20); --원상복구




------- *** tbl_sawon 테이블의 컬럼에 주어진 default 값을 조회하기 *** -----------------

select column_name, data_default

from user_tab_columns

where table_name = 'TBL_SAWON';


------- *** tbl_sawon 테이블의 jik칼럼의 default 값 변경하기 *** -----------------

alter table tbl_sawon

modify jik default '대리'; -- 변경방법


alter table tbl_sawon

modify jik default '사원'; --원상복구


--default 하면 자동으로 사원이됨

insert into tbl_sawon values(1006,'육미자','8510012234567',default, default, 10);

commit;


select *

from tbl_sawon;


--------- *** default인 정보 넣기 *** -----------------

insert into tbl_sawon values(1007,'칠미자','8510012234567', 10); --요렇게 하면 이미만들어진컬럼은 6개인데 값을 4개만 주니까 값이충분치않다고 에러가뜸.

insert into tbl_sawon(sawonno, saname, jubun, buno) values(1007,'칠미자','8610012234567', 10); -- 컬럼네임뒤에 ()로 치고 들어갈항복을 써주면 가능함!  차례대로 1:1로 맵핑하면됨. 이렇겐 가능함.


select *

from tbl_sawon;



------- *** 컬럼에 부여한 default 값 제거하기 *** -----------------

alter table tbl_sawon

modify jik default null; -- null로 바꾸면됨


insert into tbl_sawon(sawonno, saname, jubun, buno) values(1008,'팔미자','8710012234567', 10);


commit;


select *

from tbl_sawon; -- 팔미자 직급 null 




------- *** 컬럼 추가하기 *** -----------------

tbl_sawon 테이블에 email 이라는 컬럼을 추가해봅시다.


alter table tbl_sawon add email varchar2(50);  --  alter table (해당테이블) add (추가할칼럼명) (데이터타입);



------- *** 컬럼 삭제하기 *** -----------------

tbl_sawon 테이블에 email 이라는 컬럼을 삭제해봅시다.


alter table tbl_sawon drop column email;  --  alter table (해당테이블) drop column (삭제할컬럼명); 


------- *** 컬럼 추가하기2 *** -----------------

--[문제] tbl_sawon 테이블에 email 이라는 컬럼을 추가해봅시다.

--      그런데 추가하는 email 컬럼은 not null 이어야 한다.


alter table tbl_sawon add email varchar2(50) not null; -- 하지만 이미 해당테이블에 데이터가 존재하고있어서 안됨. 텅비어있어야한다.

alter table tbl_sawon add email varchar2(50) default ' ' not null; --일단 default 를 넣어주고 우리가 봤을땐 null이나 공백이나 같은거다. 그다음 다시업데이트해주면됨.


select *

from tbl_sawon; 




------- *** tbl_sawon 테이블에 존재하는 제약조건 조회하기 *** -----------------

제약조건의 5가지 종류

1. primary key  => 표기방법 P

2. unique key   => U

3. check         => C

4. foreign key  => R

5. not null     => C


--요렇게 조회하면 됨~~~

select *

from user_constraints

where table_name = 'TBL_SAWON';



--컬럼명까지 보고싶다하면

select *

from user_cons_columns

where table_name= 'TBL_SAWON';


--일반적으로 다같이 조인해서 본다.

select *

from user_constraints A join user_cons_columns B

on A.constraint_name = B.constraint_name

where A.table_name= 'TBL_SAWON';



------- ***  제약조건의 내용을 변경하기 *** -----------------

순서

1. 변경하려는 제약조건을 제거하기.

2. 제약조건을 추가하기


--1. 변경하려는 제약조건을 제거하기.

alter table tbl_sawon

drop constraint CK_TBL_SAWON_JIK;


--2. 제약조건을 추가하기

alter table tbl_sawon

add constraint CK_TBL_SAWON_JIK check(jik in('사장','부장','차장','과장','대리','사원'));




------- ***  테이블을 삭제하기 *** -----------------


drop table tbl_buseo; --자식이 참조하고있으니까 못지운다 . 자식부터 지워야함.

drop table tbl_sawon; --자식삭제


select * from tbl_sawon;


drop table tbl_panmae_201603;

select * from tbl_panmae_201603;


drop table tbl_panmae_201604;

select * from tbl_panmae_201604;


--create , alter , drop은 오토커밋임. 롤백이안댐.  


------- ***  삭제한것을 휴지통에서 꺼내오기  *** -----------------

 

select *

from user_recyclebin; --이것이 휴지통임.


--한번보기

select *

from "BIN$CPFBPKt3QAi854RHpZHQSw==$0";


--휴지통에 복원하기

flashback table TBL_SAWON to before drop; -- 이것이 복구하는것 flashback table (오리지날 테이블명) to before drop 

select * from tbl_sawon; --복원하니 다시나옴

flashback table TBL_PANMAE_201603 to before drop;

flashback table TBL_PANMAE_201604 to before drop;



------- ***  삭제한것을 휴지통에서 영구히 삭제하기  *** -----------------


--휴지통에 있는것을 필요없을때 영구히 버리는것


--일단 테스트겸 테이블을 만들겠음.

create table tbla

(no number);

insert into tbla values(1001);


create table tblb

(no number);

insert into tblb values(2001);


create table tblc

(no number);

insert into tblc values(3001);


commit;

-- create, drop, alter 으로 시작하는 명령어를 DDL (Data Definition Language 데이터정의어)라고하고 그것은 auto commit 이다.


select *

from tbla;


select *

from tblb;


select *

from tblc;


--휴지통으로 보내기~

drop table tbla;

drop table tblb;

drop table tblc;



select *

from user_recyclebin; --휴지통보기 


-- 휴지통에서 제거하기 (영구히 삭제하기) B는 살리고 나머지 A,C 지워보겠음.

purge table TBLA;

purge table TBLC;

flashback table TBLB to before drop;


select *

from user_recyclebin; --휴지통보기 / 다없어졌지만 B는 살아서 다시돌아감 A와 C는 이제 영영볼수없다.



-- 휴지통속 몽땅다 제거하기 ( 휴지통속 모두 영구히 삭제 )

purge recyclebin; --깡그리비우는것 



--테이블 삭제시 휴지통에 버리지 않고 바로 영구히 삭제하기

--일단 삭제할것을 만들고

create table tbld

(no number);

insert into tbld values(4001);


--그자리에서 바로 삭제해 버리기

drop table tbld purge;

select *

from user_recyclebin;



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

    ------------- ************** index(인덱스) ************** ---------------- 

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

적절한 인덱스를 넣으면 속도가 빨라지고 , 인덱스를 많이 넣으면 느려질수 있다.


create index 인덱스명

on 만들테이블명 (컬럼명)

--             (성,이름) -여기서 성이 선행컬럼

--             (이름,성) -이름이 선행컬럼

--1.선택도가 좋은 컬럼이어야 함

--2.단독으로 where 절에 많이 타는 컬럼이어야 함



--쓰는법

create index idx_employees_firstname

on employees(first_name);


create index idx_employees_ename

on employees(first_name, last_name);


-- create unique index idx_employees_firstname -- unique를 쓸수있고. 쓰면 중복되는것이 못들어옴. 그렇기때문에 주민번호 학번 군번 이럴때 쓰는게 좋다.


--생성되어진 index를 조회하기 --

select *

from user_indexes

where table_name = 'EMPLOYEES'; -- 생성한 인덱스 보여주기.


--컬럼에 대한정보까지 나오게하려면

select *

from user_ind_columns

where table_name = 'EMPLOYEES';


--인덱스는 무조건 오름차순. 내림차순을 하고싶다면 

create index idx_employees_firstname2

on employees(first_name desc); -- 내림차순정렬 


--보통 조인시켜서 봄. 

select *

from user_indexes A join user_ind_columns B

on A.index_name = B.index_name

where A.table_name='EMPLOYEES'


-- 인덱스 삭제하기 

drop index idx_employees_firstname2; -- drop index (인덱스명);



-- 프라이머리나 유니크를 쓰면 인덱스가 자동생성되는것을 보려고함.

create table tbl_student

(

hakbun  varchar2(10) not null

,name  varchar2(20)

,jubun varchar2(13)

,addr varchar2(100)

,constraint PK_tbl_student_hakbun primary key(hakbun)

,constraint UQ_tbl_student_jubun unique(jubun)

);


select *

from user_indexes A join user_ind_columns B

on A.index_name = B.index_name

where A.table_name='TBL_STUDENT';



--인덱스삭제하기 ->프라이머리키와 유니크를 쓴 인덱스는 제약조건을 없애버리면 자동적으로 없어진다. 

drop index idx_PK_TBL_STUDENT_HAKBUN; -- 오류 (이거아님)


--프라이머리로된것 제약조건 없애버리는것

alter table tbl_student

drop constraint PK_tbl_student_hakbun;


select *

from user_indexes A join user_ind_columns B

on A.index_name = B.index_name

where A.table_name='TBL_STUDENT'; -- 제약조건없애니까 프라이머리인덱스 없어짐. 


--유니크까지없애보자

alter table tbl_student

drop constraint UQ_TBL_STUDENT_JUBUN;



select *

from user_indexes A join user_ind_columns B

on A.index_name = B.index_name

where A.table_name='TBL_STUDENT'; -- 모두 없어짐. ㅋ


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


         -------- **** JOB 스케줄러 테스트 **** ----------

JOB 스케줄러란? 

==> 지정된 시간에 특정 업무(프로시저)가 자동적으로 발생되어지도록 만들어주는 것.


--SYS에서 작업시작

pmorauser 사용자가 JOB 스케줄러를 만들수 있도록 SYS에서 권한을 부여해주어야 한다.



grant create table to pmorauser;

grant create any job to pmorauser;


select value from v$parameter where name like '%job%';

-- 여기에 나오는 job_queue_processes 의 value 값은 job 을 몇개 까지 

-- 만들어 줄수 있는지 갯수를 말한다.

-- 기본값은 4 인데 이 값이 0 이면 job 을 만들수가 없으므로 주의를 요한다.

-- 우리는 아래처럼 해서 10개 까지 늘려본다.

alter system set job_queue_processes = 10;


select value from v$parameter where name like '%job%';

--SYS에서 작업끝



--PMORAUSER 에서 작업시작 

------  데이터를 주기적으로 검사해서 자동으로 status 컬럼의 값이 1 에서 0 으로 update 되도록 하는 테이블 생성 -------

create table tbl_jobtest

(seqcode       varchar2(20)

,name          varchar2(20)

,content       varchar2(100)

,opendate      date 

,status        number(1) default 1 

,updatedate    date default sysdate

,constraint  tbl_seq_PK primary key(seqcode)

);


--drop table tbl_jobtest purge;

--drop sequence seq_tbl_jobtest;


create sequence seq_tbl_jobtest

start with 1

increment by 1

nomaxvalue

nominvalue

nocycle

nocache;



select seqcode, name, content, 

       to_char(opendate, 'yyyy-mm-dd hh24:mi:ss') as opendate,

       status,

       to_char(updatedate, 'yyyy-mm-dd hh24:mi:ss') as updatedate

from tbl_jobtest;



-- 테이블 tbl_jobtest 에 insert 하는 프로시저생성

create or replace procedure pcd_tbl_jobtest_insert

(p_name       in  tbl_jobtest.name%TYPE -- tbl_jobtest.의 name값의 타입을 말한다. / 값을 입력받을때 변수의 데이터타입을 쓸때 varchar2(20)같은 싸이즈를 쓰면 안된다.

,p_content    in  tbl_jobtest.content%TYPE

,p_opendate   in  tbl_jobtest.opendate%TYPE

)

is

   v_seq  number; -- 여기는 사이즈 잡아도 아무 문제 없다.

begin

     select seq_tbl_jobtest.nextval into v_seq

     from dual;

     

     insert into tbl_jobtest values

     ('KH'||to_char(sysdate, 'yyyymmdd')||v_seq , p_name , p_content, p_opendate , default, default);

     

     commit;

end pcd_tbl_jobtest_insert;



exec pcd_tbl_jobtest_insert('한석규','한석규 주연 영화입니다.', to_date('2016-10-04 21:17:00','yyyy-mm-dd hh24:mi:ss'));

exec pcd_tbl_jobtest_insert('두석규','두석규 주연 영화입니다.', to_date('2016-10-04 21:18:00','yyyy-mm-dd hh24:mi:ss'));

exec pcd_tbl_jobtest_insert('세석규','세석규 주연 영화입니다.', to_date('2016-10-04 21:19:00','yyyy-mm-dd hh24:mi:ss'));

exec pcd_tbl_jobtest_insert('네석규','네석규 주연 영화입니다.', to_date('2016-10-04 21:20:00','yyyy-mm-dd hh24:mi:ss'));

exec pcd_tbl_jobtest_insert('오석규','오석규 주연 영화입니다.', to_date('2016-10-04 21:21:00','yyyy-mm-dd hh24:mi:ss'));

exec pcd_tbl_jobtest_insert('육석규','육석규 주연 영화입니다.', to_date('2016-10-04 21:22:00','yyyy-mm-dd hh24:mi:ss'));



select seqcode, name, content, 

       to_char(opendate, 'yyyy-mm-dd hh24:mi:ss') as opendate,

       status,

       to_char(updatedate, 'yyyy-mm-dd hh24:mi:ss') as updatedate

from tbl_jobtest;



-- 테이블 tbl_jobtest 에 update 하는 프로시저생성

create or replace procedure pcd_tbl_jobtest_update

is

   v_seq  number;

begin

     update tbl_jobtest set status = 0, updatedate = sysdate

     where status = 1 

     and (sysdate - opendate) > 0;  

        

     commit;

end pcd_tbl_jobtest_update;



------ ***** JOB Scheduler 생성하기 ****** --------

-- JOB 등록하기 --

-- 여기서는 프로시저 pcd_tbl_jobtest_update 를 JOB 으로 설정하도록 한다.

DECLARE

  jobno NUMBER;

BEGIN

  SYS.DBMS_JOB.SUBMIT

    ( job       => jobno  

     ,what      => 'PMORAUSER.PCD_TBL_JOBTEST_UPDATE;'

     ,next_date => to_date('2016-10-04 21:18:00','yyyy-mm-dd hh24:mi:ss')

     ,interval  => 'SYSDATE + 1/(24*60)'

     ,no_parse  => TRUE

    );

END;



--* job : 실행할 job number   기본적으로 1부터 들어옴.

--* what - 실행할 PL/SQL 프로시저(procedure) 명 혹은 psm 문장의 sequence

--* next_date - job을 언제 처음 시작할 것인지 지정한다. date type으로 evaluate되는 문자열 입력(SYSDATE)

--* interval - job을 수행한 후, 다음 실행시간까지의 시간을 지정한다. 

--                위 셋팅 'SYSDATE + 1/(24*60)' 은 1분마다 실행한다.

--* no_parse - true 이면 submit시에 job을 parsing하지 않는다.



-- *** 프로시저 소스 보기

select text

from user_source

where type='PROCEDURE' and name='PCD_TBL_JOBTEST_UPDATE';


--  job queue 정보 조회

SELECT * FROM USER_JOBS;



-- 몇분이 지난후 아래를 실행해본다.

select seqcode, name, content, 

       to_char(opendate, 'yyyy-mm-dd hh24:mi:ss') as opendate,

       status,

       to_char(updatedate, 'yyyy-mm-dd hh24:mi:ss') as updatedate

from tbl_jobtest;



-- JOB 지금바로 실행하기 -- 여기서  숫자 1은 job 의 번호 임.  

SELECT job FROM USER_JOBS;


execute dbms_job.run(1);

commit;



-- JOB 정지 --  여기서  숫자 1은 job 의 번호 임.  

SELECT job FROM USER_JOBS;


execute dbms_job.broken(1, true);

commit;



-- 정지된 JOB 재시작 --  여기서  숫자 1은 job 의 번호 임.  

SELECT job FROM USER_JOBS;


execute dbms_job.broken(1, false);

commit;



-- JOB 삭제 --  여기서  숫자 1은 job 의 번호 임.  

SELECT job FROM USER_JOBS;


execute dbms_job.remove(3);

commit;


-- JOB 변경 next_date  -- 여기서  숫자 1은 job 의 번호 임.  

SELECT job FROM USER_JOBS;


execute dbms_job.next_date(1, trunc(sysdate)+1+1/24/60);

commit;




**** job Interval 설정

ex)

SYSDATE+7 : 7일에 한번 씩 job 수행

SYSDATE+1/24 : 1시간에 한번 씩 job 수행

SYSDATE+30/ : 30초에 한번 씩 job 수행(24: 시간 당, 1440(24x60):분 당, 86400(24x60x60):초 당 )

TRUNC(SYSDATE, 'MI')+8/24 : 최초 job 수행시간이 12:29분 일 경우 매시 12:29분에 job 수행

TRUNC(SYSDATE+1) : 매일 밤 12시에 job 수행

TRUNC(SYSDATE+1)+3/24 : 매일 오전 3시 job 수행

NEXT_DAY(TRUNC(SYSDATE),'MONDAY')+15/25 : 매주 월요일 오후 3시 정각에 job 수행

TRUNC(LAST_DAY(SYSDATE))+1 : 매월 1일 밤 12시에 job 수행

TRUNC(LAST_DAY(SYSDATE))+1+8/24+30/1440 : 매월 1일 오전 8시 30분






--- sys 였었던 부분


show user;


-- sys의 권한으로 pmorauser라는 이름으로 새로운 접속을 할 수 있게 해주기.

create user pmorauser identified by pmorauser

default tablespace users;


-- sys의 권한으로 다른 접속에서 처리할수있게끔하기

grant connect,resource,unlimited tablespace, create view to pmorauser;


-- 오라클사에서 기본적으로 제공하는 hr 계정 잠긴것 풀기.

alter user hr account unlock;

alter user hr IDENTIFIED by hr;


--

create user oppacar identified by oppacar

default tablespace users;


grant connect,resource,unlimited tablespace, create view to oppacar;



show user;


--파이널 프로젝트 오라클 유저 id / passwd ==> p_commit 

create user p_commit identified by p_commit

default tablespace users;

--

grant connect,resource,unlimited tablespace, create view to p_commit;


-- 파이널전 테스트 하는것.

create user f_test identified by f_test

default tablespace users;

--

grant connect,resource,unlimited tablespace, create view to f_test;







select *

from dba_users;


--오라클사에서 공부를 위해 제공해주고 있는 샘플용 오라클 일반사용자 계정이 있다.


alter user hr account unlock; --잠긴 계정을 푸는것


alter user hr identified by hr; -- 암호를 새로이 부여하는것 




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

         ---------- JDBC ------------ 

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

show user;



--오라클 사용자 계정생성하기

create user pmorauser identified by pmorauser

default tablespace users;


grant connect,

       resource,

       unlimited tablespace,

       create view to pmorauser;

       

       

       

       

       

       

       

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


         


Comments