프로필

시스템에 대한 허접한 모든것들이..
by joon
이전블로그
한번에 가자..
이글루링크
2006년 12월 09일〃posted title : 댓글로 글 남겨주세요....
^^;; 흔적표시~~귀찮아도 남겨주삼~~
by joon | 2006/12/09 10:51 | 방명록 | 트랙백 | 덧글(11)
2006년 10월 23일〃posted title : 그룹 함수

-------------------------------------------------------------------------------------
- 제 8장 - 그룹 함수
-------------------------------------------------------------------------------------

--> group by 사용시 첫 번째 컬럼으로 오름차순 정렬이 자동으로 이루어진다.

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

* avg

--> 오라클 - 소수점까지 정확한 값 출력. 몫 연산시 floor 사용해야 한다.

--> MSSQL - 반올림 --> 정수/정수=몫값만 나오기 때문이다.  

select sum(sal), count(sal), sum(sal)/count(sal),avg(sal),

       sum(comm),count(comm),sum(comm)/count(comm),avg(comm),

       count(*),sum(comm)/count(*),avg(nvl(comm,0))

from emp;

--> 그룹함수 연산에서 널값은 자동적으로 제외한다.

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

* rollup 

select deptno, job, sum(sal)

from emp

group by deptno, job;

select deptno, job, sum(sal)

from emp

group by rollup(deptno, job);

--> 동일한 부서번호간의 급여의 총합 & 모든 사람의 급여 총 합  

select deptno, job, sum(sal)

from emp

group by cube(deptno, job);

--> 부서별 뿐만 아니라, 직종별 합 역시 알려준다.

--> MSSQL

select deptno, job, sum(sal)

from emp

group by deptno, job with rollup;

select deptno, job, sum(sal)

from emp

group by deptno, job with cube;

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

* 예제 ) 부서별 급여의 합이 9000이 넘는 부서명과 총 급여를 출력하라.  

select deptno, sum(sal)

from EMP

group by deptno

having sum(sal) >= 9000;

--> from -> group by -> select -> having

--> select <--> group by / select 2번째 <-> having

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

* 예제 ) 아래와 같이 출력 하라.

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

  성 별       인 원 수  

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

   남            3

   여            3

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

방법 1) 인라인쿼리의 작성 순서.

1)

  select case when substr(jubun,7,1) in ('1','3','5') then '남'

               else '여' end 성별

  from MEMBER

2)

  (

  select case when substr(jubun,7,1) in ('1','3','5') then '남'

               else '여' end 성별

  from MEMBER

  ) T

3)

  select 성별,count(*) 인원수

  from

  (

  select case when substr(jubun,7,1) in ('1','3','5') then '남'

           else '여' end 성별

  from MEMBER

  ) T

  group by 성별 ;

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

방법 2)

 select case when substr(jubun,7,1) in ('1','3','5') then '남'

          else '여' end 성별, count(*) 인원수

 from member

 group by case when substr(jubun,7,1) in ('1','3','5') then '남'

          else '여' end;

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

 예제 2) 아래와 같이 출력하시오.

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

  연령대    인원수     

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

    30        3

    20        1

     0        2

select floor(나이대/10)*10 연령대,count(*) 인원수

from

(

select case when substr(jubun,7,1) in ('1','2','5','6')  

       then (extract(year from sysdate) - (to_number(substr(jubun,1,2))+1899))

       else extract(year from sysdate) - (to_number(substr(jubun,1,2))+1999)

       end 나이대

from member

) T

group by floor(나이대 /10)*10;

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

예제) 아래와 같이 출력하시오.

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

 부서번호  직종  급여의합

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

select deptno,job,sum(sal)

from EMP

group by deptno,job

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

예제) 아래와 같이 출력하시오.

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

 연령대 성별 인원수

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

select floor(나이대/10)*10 연령대,성별,count(*) 인원수

from

(

select case when substr(jubun,7,1) in ('1','2','5','6')  

       then (extract(year from sysdate) - (to_number(substr(jubun,1,2))+1899))

       else extract(year from sysdate) - (to_number(substr(jubun,1,2))+1999)

       end 나이대,

       case when substr(jubun,7,1) in ('1','3','5') then '남'

       else '여' end 성별

from member

) T

group by floor(나이대 /10)*10,성별; 

-->

0   남  1

0   여  1

20  여  1

30  남  2

30  여  1

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

* EMP테이블에서 ANALYST팀을 제외하고, 직원총급여가 5500이 넘는

 직종과 총급여를 출력하시오.

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

--> 직종별 총급여 출력

select job,sum(sal)

from EMP

group by job

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

--> group by에서는 having절에 조건이 들어간다.

select job,sum(sal)

from EMP

where job <> 'ANALYST' --> 대소문자 주의 not 'analyst'!!!!!!!

group by job

having sum(sal) >=5500;

--> 메모리 로드시 analyst직종 제외하므로, 성능적으로 하단의 구문에 비해 우수하다.

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

다른방법)

select job, sum(sal)

from EMP

group by job

having job <> 'ANALYST' and sum(sal) >=5500;

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

8장 연습문제

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

1. EMP테이블에서 인원수,최대급여,최소급여,급여의 합을 출력

select count(*),max(sal),min(sal),sum(sal)

from EMP;

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

2. EMP테이블에서 각 업무별로 최대급여,최소급여,급여의 합 출력

select job,max(sal),min(sal),sum(sal)

from EMP
group by job;

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

3. EMP테이블에 업무별 인원수 출력

select job,count(*)
from EMP
group by job;

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

4. EMP 테이블에서 최그급여와 최소 급여의 차이를 출력하시오.

select max(sal)-min(sal) "급여 차이"
from EMP;

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

5. EMP테이블에서 입사년도 별로 총인원,최소,최대,평균,총급여를 출력하라

----------------------------------------------------------------
H_Year Count(*) MIN(SAL) MAX(SAL) AVG(SAL) SUM(SAL)
----------------------------------------------------------------
  80           1           800           800              800       800
  81          10          950          5000          2282.5      22825
 

select count(*),min(sal),max(sal),avg(sal),sum(sal)
from EMP
group by to_char(hiredate,'YY')

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

6. EMP 테이블에서 년도별 입사인원을 아래와 같이 출력하라.


---------------------------------------------
TOTAL 1980 1981 1982 1983 1987
---------------------------------------------
   14      1      10       2    0       1

select count(*) "TOTAL",
       sum(decode(to_char(hiredate,'yyyy'),'1980',1,0)) "1980",
       sum(decode(to_char(hiredate,'yyyy'),'1981',1,0)) "1981",
       sum(decode(to_char(hiredate,'yyyy'),'1982',1,0)) "1982",
       sum(decode(to_char(hiredate,'yyyy'),'1983',1,0)) "1983",
       sum(decode(to_char(hiredate,'yyyy'),'1987',1,0)) "1987"
from emp
where to_char(hiredate,'yyyy') between '1980' and '1987';

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

7. EMP테이블에서 아래와 같이 부서/직종별 급여의 총합을 구하시오.

--------------------------------------------------
JOB        Deptno_10 Deptno_20 Deptno_30 Total
--------------------------------------------------
ANALYST                  6000                      6000
CLERK        1300        1900         950        4150
.......
 

select job,
       sum(decode(deptno, 10, sal)) "Deptno 10",
       sum(decode(deptno, 20, sal)) "Deptno 20",
       sum(decode(deptno, 30, sal)) "Deptno 30",
sum(sal) "Total"
from emp
group by job;

by joon | 2006/10/23 22:33 | Oracle | 트랙백 | 덧글(0)
2006년 10월 23일〃posted title : 단일 행 함수

-------------------------------------------------------------------------------------
- 제 7장 - 단일 행 함수
-------------------------------------------------------------------------------------

* initcap - 첫번째 영문자만 대문자로 바꾸어준다.

select ename, initcap(ename) from emp; 

--> 결과값 : KEVIN --> Kevin

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

* concat - 문자열 합치기. ||와 같으나 최대 2개만 가능

select ename || job || deptno, concat(ename,job) from emp;

--> 결과값 : SMITHCLERK20 / SMITHCLERK
 

select ename || job || deptno, concat(ename,job,deptno) from emp;

--> 에러 : concat에는 최대 2개까지만 가능..

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

* substr - 글자 수 기준 문자열 추출 , substrb - 바이트기준 문자열 추출

select substr('oracle',1,3), substr('대한민국',1,2) from dual; 


--> 결과값 : ora , 대한 (바이트와 상관없다.)

select substrb('oracle',1,3), substrb('대한민국',1,1) from dual;


--> substrb 는 바이트기준으로 출력한다. 한글은 2바이트,영문 1바이트

--> 결과값 : ora /  (3byte ora / 한글은 2바이트이기때문에 출력불가)

select substr('oracle',2) from dual;


--> 결과값 : racle ( 2번째 문자부터 끝까지 )

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

 * length - 글자수,비영어권에서 보편적임 , lengthb - 바이트수

select length('oracle'),length('대한민국'),
          lengthb('oracle'),lengthb('대한민국') from dual;

 --> 결과값 : 6 / 4 (4글자기준) / 6 / 8 (4글자 8byte기준)
       

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

* instr - 특정 문자열이 처음 발견 된 위치 값 리턴

select instr('oracle ORACLE oralb','ora',1),
         instr('oracle ORACLE oralb','ora',2),
         instr(lower('oracle ORACLE oralb'),lower('ora'),2)

from dual;

--> 결과값 : 1 / 15 / 8 (대소문자구분없이하기위해 소문자로 형변환)

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

        
* lpad, rpad - 특정 크기를 지정하여 공백부분에 특정 문자열로 채워준다.

                      숫자는 바이트라는 것에 절대 유의하자.

select lpad('오라클',20,'?'), lpad('?',20,'?'),rpad('?',20,'?'),rpad('오라클',20,'?') from dual;

--> 결과값 :

??????????????오라클 / ???????????????????? / ???????????????????? / 오라클??????????????

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

* ltrim , rtrim - 특정 문자열 혹은 공백 제거


select ltrim('오오징어오라클','오징' ), ltrim('오오징어오라클','클라' ),
       rtrim('오오징어오라클','오징' ), rtrim('오오징어오라클','클라' ),
    rtrim('오징어             ') ,ltrim('             오징어') ,
       rtrim(ltrim ('               오오징어오라클                ') )
from dual;

--> 결과값 :

어오라클 / 오오징어오라클 / 오오징어오라클 / 오오징어오 / 오징어 / 오징어 / 오오징어오라클

rtrim은 오른쪽에서 부터 제거되는 대신에, 지정 문자역시 뒤집어 입력해야한다.

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

* translate - 특정 문자열을 사용자가 지정한 매칭값으로 바꿔준다.

select translate('oracle',
                      'abcdefghijklmnopqrstuvwxyz',
                     'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
from dual;


--> 결과값 'ORACLE' - 대소문자 변환이 되었다.

select translate('공공칠빵',
                      '공일이삼사오육칠팔구빵',
                      '01234567890')
from dual;


--> 결과값 : 0070 (바뀌어질 것과 바뀌는 것의 타입은 전혀 상관없다.)

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

* replace - 문자열 바꾸기, 대소문자 구별..

select replace('oracle oracle9i ORACLEDBA', 'ora', '오라') from dual; 

--> 결과값 : 오라cle 오라cle9i ORACLEDBA
 

select replace(upper('oracle oracle9i ORACLEDBA'),upper('ora'), '오라') from dual; 

--> 결과값 : 오라CLE 오라CLE9I 오라CLEDBA

--> 대소문자 구별을 없애기 위해, 모든값을 대문자로 강제 형변환하였다.

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

reverse - 문자열 순서 뒤집기

select reverse('oracle oracle9i ORACLEDBA') from dual; 

--> 결과값 : ABDELCARO i9elcaro elcaro

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

* round - 반올림, 옵션 숫자가 음수면 정수자리, 양수면 소수자리 반올림

select 91.459, round(91.459,-3),round(91.459,-2) , round(91.459,-1) ,round(91.459,0) ,
       round(91.459,1) ,round(91.459,2), round(91.459,3)
from dual;

--> 결과값 : 91.459 / 0 / 100 / 90 / 91 / 91.5 / 91.46 / 91.459

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

* trunc - 숫자 절삭, 옵션 숫자가 음수면 정수자리, 양수면 소수자리

select 91.459, trunc(91.459,-3),trunc(91.459,-2) , trunc(91.459,-1) ,trunc(91.459,0) ,
       trunc(91.459,1) ,trunc(91.459,2), trunc(91.459,3)
from dual;

--> 결과값 : 91.459 | 0 | 0 | 90 | 91 | 91.4 | 91.45 | 91.459

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

* mod(나머지), power(제곱), sqrt(루트)

select mod(5,2), power(5,2), sqrt(2) from dual;
--> 결과값 : 1 / 25 / 1.4142135623731

* sign

select sign(5-2), sign(5-5), sign(2-5), sign(-3) from dual;
--> 결과값 : 1 / 0 / -1 / -1

* chr - ascii 코드에 해당하는 문자 리턴
select chr(65), chr(97), ascii('A'),ascii('a') from dual;
--> 결과값 : A / a / 65 / 97

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

-- 1.5.2 날짜 연산 (p.113)
-------------------------------------------------------------------------------------

* sysdate


select sysdate+1 , sysdate-1,sysdate-1/24,sysdate+1/24 from dual; 
--> 1 일 증감, 1시간 전,  1시간 후


select sysdate - to_date('2006-10-13', 'yyyy-mm-dd') from dual;
--> 1.67614583333333 (현재 날짜시간에서 해당날짜를 뺀 값, 대략 1.6일정도) 

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

* to_date

select to_date('2006-10-13', 'yyyy-mm-dd') from dual;
--> 2006-10-13 00:00:00


select to_date('20061013','yyyymmdd') from dual;
--> 2006-10-13 00:00:00


select to_date('20060931','yyyymmdd') from dual;
--> 에러.. 달력에9월 31일은 존재하지 않는다.

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

* months_between - 달 차이 구하기. (9월과 5월은 4달...)


select months_between('20061014','20060914') from dual;
--> 1 (1달 뒤)


select months_between('20060914','20061014') from dual;
--> -1 (1달 전)


select months_between(sysdate,'20060901') from dual;
--> 1.44128136200717 (대략 1달 보름)

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

* add_months -달 계산


select add_months(sysdate,2) from dual;
--> 2006-12-14 16:19:44 (현재 시각에 2달을 더하기.)


select add_months(sysdate,-2) from dual;
--> 2006-08-14 16:20:02 (현재 시각에 2달을 뺐다.)

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

* next_day - 가장 최근에 돌아오는 특정요일의 날짜 검색

select next_day(sysdate,'FRI') from dual;
select next_day(sysdate,'FRIDAY') from dual;

--> 돌아오는 금요일의 날짜와 현재와 같은 시각 리턴

select next_day(sysdate,'금') from dual;
select next_day(sysdate,'금요일') from dual; 
--> 한글은 sqlgate에서 실행불가, sqlplus에서 실행하자.

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


* last_day - 특정 월의 마지막 날짜 

select last_day(sysdate) from dual;

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

* 현재시각을 기준으로 특정값만 추출 --> 숫자 출력

select sysdate,
    to_char(sysdate,'yyyy') 년,to_char(sysdate,'mm') 월,
    to_char(sysdate,'dd') 일 , to_char(sysdate,'hh') 시,
    to_char(sysdate,'mm') 분,to_char(sysdate,'ss') 초
from dual;
--> 2006 10 15 03 10 42

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

* 현재시각을 기준으로 특정값만 추출 #2  --> 영문출력

select sysdate,  -- mon <-> month 같다 dy <-> day
    to_char(sysdate,'year') 년,to_char(sysdate,'month') 월,
    to_char(sysdate,'day') 일 ,to_char(sysdate,'hh') 시,
    to_char(sysdate,'mm') 분,to_char(sysdate,'ss') 초 ,
    to_char(sysdate,'dy')
from dual;
-->two thousand sixoctober  sunday   03 10 02

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

* 분기 (quarter) , 몇째 주  , 그 해의 주차, 요일에 해당하는 숫자

select to_char(sysdate,'q'), to_char(sysdate,'w'),
       to_char(sysdate,'ww'),to_char(sysdate,'d'),
    to_char(sysdate,'dd'),to_char(sysdate,'ddd')
from dual;
--> 4(4분기), 3(10월 3째주), 42(2006년 42주차),
--- 2 (월요일), 16(16일), 289(2006년 289일째) d / dd / ddd

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

* 요일값 구하기

--> to_char(sysdate,'d') 
--> 리턴값은 다음과 같은 숫자 - 일요일(1) 월(2) 화(3)수(4)목(5)금(6)토(7)


리눅스기반 오라클에서 리턴값 한글로 강제 변환 방법

1) 방법 1  (case구문은 oracle 9i 부터 사용)

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 "오늘의 요일명"   --> alias , 쌍따옴표 주의!!
from dual;

2) 방법 2

select case
       when to_char(sysdate,'d')='1' then '일요일'
       when to_char(sysdate,'d')='2' then '월요일'
       when to_char(sysdate,'d')='3' then '화요일'
       when to_char(sysdate,'d')='4' then '수요일'
       when to_char(sysdate,'d')='5' then '목요일'
       when to_char(sysdate,'d')='6' then '금요일'
       when to_char(sysdate,'d')='7' then '토요일'
       end "오늘의 요일명"
from dual;

3) 방법 3 (오라클 8i 이전에 주로 사용..)

select decode(to_char(sysdate,'d'),'1','일요일'
                                   ,'2','월요일'
                                   ,'3','화요일'
                                   ,'4','수요일'
                                   ,'5','목요일'
                                   ,'6','금요일'
                                   ,'7','토요일')
"오늘의 요일명"
from dual;                              

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

* 현재 시각 (표준시각 current_date)

select sysdate, current_date from dual;

--> 2006-10-19 20:20:14(시스템시간) / 2006-10-19 11:20:15(세계표준시)

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

* 날짜 타입 서수형으로의 변환

select to_char(sysdate, 'yyspth'),to_char(sysdate, 'mmspth'),
       to_char(sysdate, 'ddspth')
from dual;
--> sixth tenth sixteenth (200 '6'년 '10'월 '16'일)

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

* 현재 날짜 원하는 형식으로 변환

select to_char(sysdate,'yyyy"년" mm"월" dd"일"')
from dual;
--> 2006년 10월 16일

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

* 'fmyyyy-mm-dd' 날짜중 0을 제거/삽입 

select ename, to_char(hiredate,'yyyy-mm-dd') hiredate,
       to_char(hiredate,'fmyyyy-mm-dd') hiredate, --> 제거 
      to_char(hiredate,'fmyyyy-mmfm-dd') hiredate --> /yyyy제거 mm삽입 
from emp;
--> 1981-04-02 -> 1981-4-2 (0을 삭제하자.)

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

* 통화기호와 자리표시

select ename,sal,
       to_char(sal,'09999'),  --> 00800   --> 01600
       to_char(sal,'$9,999'), -->  $800   --> $1,600
       to_char(sal,'L9,999')  -->  $800   --> $1,600
from emp;

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

* 현재 설정 (언어, 통화, 달력등 보기)

select * from v$nls_parameters;

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

* 날짜 계산


select '20061016'-'20061010'
from dual;
--> 6 (문자열 숫자열로 오라클 서버가 자동 형변환)

select sysdate-'20061010'
from dual;
--> 에러

select to_char(sysdate,'yyyymmdd')-'20061010'
from dual;
--> 6 (강제형변환을 해주어야한다)

select sysdate - to_date('20061010','yyyymmdd')
from dual;
--> 6.43899305555555

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

* to_yminterval


select sysdate, add_months(sysdate,14),
       sysdate + to_yminterval('01-02') -- only Oracle 9i upper!
from dual; 
--> 2006-10-16 10:33:15 / 2007-12-16 10:33:15 / 2007-12-16 10:33:15
--- 14개월 / 1년 2개월 후 

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

* to_dsinterval


select sysdate + to_dsinterval('001 02:03:04')
from dual;
--> 1일 2시간 3분 4초 후... / 2006-10-17 12:37:41

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

* to_yminterval + to_dsinterval


select sysdate
     + to_yminterval('01-02')
     + to_dsinterval('001 02:03:04')
from dual;
--> 1년 2월 1일 2시간 3분 4초 후.. / 2007-12-17 12:39:39

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

* extract - Oracle 9i이상에서만 동작한다.

    --> 날짜데이터에서 특정값을 숫자형으로 추출..(우측정렬)
    --> to_char와 결과물은 같지만, to_char는 문자열이다.(좌측)


select sysdate,
       extract(year from sysdate),
       to_char(sysdate,'yyyy'),   
       extract(month from sysdate),
       to_char(sysdate,'mm'),
       extract(day from sysdate)+1,  --> 원래 숫자형이므로 형변환 X
       to_char(sysdate,'dd')+1  --> 1을 더하면서 강제형변환이 일어났다.
from dual;

-->

2006-10-19 20:28:53 / 2006(우) / 2006(좌) / 10(우) / 10(좌) / 20(우) / 20(우)

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

* 실수로 반복 입력한 데이터의 삭제.. --> rowid와 rownum을 이용..

select rownum, rowid, name,jubun
from member;

--> 잘못입력된 데이터의 데이터 입력시 자동생성되는 rowid와 rownum을 검색하자

delete member
where rowid like 'AAAHZuAAJAAAAAP%';

--> rowid를 검색하여, 그 행을 조건절을 이용하여 삭제.

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

* 클라이언트 정보 검색

select userenv('language') "language",
       userenv('terminal') "terminal",
       userenv('sessionid') "sessionid"
from dual;

--> 현재 설정된 언어 값 / 접속컴퓨터터미널이름 / 세션ID

AMERICAN_AMERICA.KO16MSWIN949 / MVP386 /167

select uid, user from dual;

--> 59 (USER ID) / SCOTT(접속계정)

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

* 순위 매기기

방법 1)

select ename "사원명",deptno "부서번호",sal "급여",
       rank() over(order by sal desc) "전체등수",   --공동랭크 포함 - 공동2등 다음 4등
       rank() over(partition by deptno order by sal desc) "부서별등수",
       dense_rank() over(order by sal desc) 전체서열, --공동랭크 불포함 - 공동2등 다음 4등
       dense_rank() over(partition by deptno order by sal desc) 부서별서열
from EMP;

방법 2) 인라인 쿼리문 - 사실상 이 문제에는 필요없다.

select *
from
(
select ename "사원명",deptno "부서번호",sal "급여",
       rank() over(order by sal desc) "전체등수",   --공동랭크 포함 - 공동2등 다음 4등
       rank() over(partition by deptno order by sal desc) "부서별등수",
       dense_rank() over(order by sal desc) 전체서열, --공동랭크 불포함 - 공동2등 다음 4등
       dense_rank() over(partition by deptno order by sal desc) 부서별서열
from EMP
) T
where "전체등수" <=10
order by 2,3 desc;

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

-- Quiz )

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

1. member 테이블에서 여자만 출력하시오.

select *

from member

where substr(jubun,7,1) in (2,4)

select *

from member

where substr(jubun,7,1) =  '2' or substr(jubun,7,1) =  '4'

--> 위의 in 구문보다 아래의 OR 구문이 대용량DB에서 속도면에서 유리하다.

--> 2와 4에 홑따옴표(')를 붙여주지 않아도 동작은 되지만, 무결성을 위해 붙여주자

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

2. 아래와 같은 테이블이 있다.

create table filetab
(fileno number,
filename varchar2(200)
) tablespace users;

insert into filetab values(1,'c:\aaa\bbb\ccc\sales.xls');
insert into filetab values(2,'d:\aaa\salesinfo.doc');
insert into filetab values(3,'c:\research.xxls');
insert into filetab values(4,'d:\aaa\bbb\marketing.hwp');

1) 확장자가 xls인 파일만 출력하시오.

select *

from filetab

where filename like '%.xls';

--> 데이터중에 .xls와 .xxls가 있다. 점(.)을 꼭 넣어 구분해주자.

2) 아래와 같이 출력하시오.

--------------------------------
 fileno      filename
--------------------------------
1            sales.xls
2            salesinfo.doc
3            research.xxls
4            marketing.hwp

-->

select fileno,

         reverse(substr(reverse(filename),1,instr(reverse(filename),'\',1)-1)) filename
from filetab;

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

Quiz ) - 2006.10.14.16:36:00

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

1. 오늘 입대하면 언제 제대할까? (군 기간은 2년)
select add_months(sysdate,24) from dual;
--> 2008-10-14 16:36:34

2. 오늘 입대하면 몇끼를 먹어야 제대할까? (단, 하루3끼)
select (add_months(sysdate,24)-sysdate)*3 from dual;
--> 2193

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

Quiz ) 아래와 같이 출력하시오.

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

 이름  주민번호 계통 성별 나이

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

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

insert into member values('귀화남','7510165234567');
insert into member values('귀화녀','7611126234567');
commit;

select * from MEMBER;

방법 1) 복잡하고 잘못된 코딩

select name 이름,jubun 주민번호,

    case when substr(jubun,7,1) in ('1','2','3','4')
       then '한국계'
      else '외국계'
    end "원래국적" ,
    decode(substr(jubun,7,1),'1','남'
                                        ,'3','남'
                                        ,'5','남'
                                       ,'여') "성별" , --> 계통


    case when substr(jubun,7,1) in ('1','2') then to_char(sysdate,'yyyy') - ('19' || substr(jubun,1,2))
         when substr(jubun,7,1) in ('3','4') then to_char(sysdate,'yyyy') - ('20' || substr(jubun,1,2))
         when substr(jubun,7,1) in ('5','6') then to_char(sysdate,'yyyy') - ('19' || substr(jubun,1,2))        
           when substr(jubun,7,1) in ('7','8') then to_char(sysdate,'yyyy') - ('20' || substr(jubun,1,2)) 
        end "현재나이"       --> 나이계산
from member;

방법 2) 간단한 코딩 

select T.*,
add_months(to_char(sysdate,'yyyy')||'-02-20',12*(60-현재나이)) "정년일",
to_date(to_char(sysdate,'yyyy-mm-dd'),'yyyy-mm-dd') - 입사일 "근무일수",
add_months(to_char(sysdate,'yyyy')||'-02-20',12*(60-현재나이)) -
to_date(to_char(sysdate,'yyyy-mm-dd'),'yyyy-mm-dd') "남은일수"
from
(
select name 성명, jubun 주민번호, hiredate 입사일,
  case when substr(jubun,7,1) in ('1','2','3','4') then '한국계'
       else '외국계' end 혈통,
  case when substr(jubun,7,1) in ('1','3','5') then '남'
       else '여' end 성별,
  case when substr(jubun,7,1) in ('1','2','5','6') 
       then extract(year from sysdate) - (to_number(substr(jubun,1,2))+1899)
       else extract(year from sysdate) - (to_number(substr(jubun,1,2))+1999)
       end 현재나이     
from MEMBER
) T;


-->
귀화인 7510165234567 외국계 남 31
귀화여 7611126234567 외국계 여 30
이순신 7001031234567 한국계 남 36
김하늘 8012252234567 한국계 여 26
남자애 0005023234567 한국계 남 6
여자애 0103014234567 한국계 여 5

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

-- 컬럼 추가
----------------------------------------------------------------------------------

alter table member
add hiredate date;

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

Quiz ) member 테이블에서 아래와 같이 추출. 단 정년은 60세 되는해의 2월 20일이다.

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

성명 주민번호 입사일 계통 성별 현재나이 근무일수 정년일 남은일수

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

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

select *
from member;

update member set hiredate=to_date('1998-01-04','yyyy-mm-dd')
where name='이순신'; 
update member set hiredate=to_date('1999-12-14','yyyy-mm-dd')
where name='김하늘'; 
update member set hiredate=to_date('2002-09-10','yyyy-mm-dd')
where name='남자애'; 
update member set hiredate=to_date('2003-03-20','yyyy-mm-dd')
where name='여자애'; 
update member set hiredate=to_date('2000-01-30','yyyy-mm-dd')
where name='귀화인'; 
update member set hiredate=to_date('2000-01-30','yyyy-mm-dd')
where name='귀화여'; 

commit;

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

정답 )

select T.*,


add_months(to_char(sysdate,'yyyy')||'-02-20',12*(60-현재나이)) "정년일",


to_date(to_char(sysdate,'yyyy-mm-dd'),'yyyy-mm-dd') - 입사일 "근무일수",


add_months(to_char(sysdate,'yyyy')||'-02-20',12*(60-현재나이)) -
to_date(to_char(sysdate,'yyyy-mm-dd'),'yyyy-mm-dd') "남은일수"


from
(
select name 성명, jubun 주민번호, hiredate 입사일,


  case when substr(jubun,7,1) in ('1','2','3','4') then '한국계'
       else '외국계' end 혈통,


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


  case when substr(jubun,7,1) in ('1','2','5','6') 
       then extract(year from sysdate) - (to_number(substr(jubun,1,2))+1899)
       else extract(year from sysdate) - (to_number(substr(jubun,1,2))+1999)
       end 현재나이     


from MEMBER
) T;

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

Quiz ) emp테이블의 사원중 1년간 총연봉(급여+보너스)가 30000이상인 사람 추출

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

방법1)

select ename, coalesce(sal*12+comm, comm, sal*12, 0)
from emp
where coalesce(sal*12+comm, comm, sal*12, 0) >= 30000;

방법2) 인라인쿼리


select *
from
(
select ename 사원명, coalesce(sal*12+comm,comm,sal*12,0) 연봉
from emp
) T
where T.연봉 >= 30000; 

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

Quiz ) 급여가 아닌 연봉으로 순위 출력

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

select *
from
(
select ename "사원명",deptno "부서번호",to_char(coalesce(sal*12+comm,comm,sal*12,0),'$999,999') "연봉",
       rank() over(order by coalesce(sal*12+comm,comm,sal*12,0) desc) "전체등수",   --공동랭크 포함 - 공동2등 다음 4등
       rank() over(partition by deptno order by coalesce(sal*12+comm,comm,sal*12,0) desc) "부서별등수",
       dense_rank() over(order by coalesce(sal*12+comm,comm,sal*12,0) desc) 전체서열, --공동랭크 불포함 - 공동2등 다음 4등
       dense_rank() over(partition by deptno order by coalesce(sal*12+comm,comm,sal*12,0) desc) 부서별서열
from EMP
) T
where "전체등수" <=10
order by 2,3 desc;       coalesce(sal*12+comm,comm,sal*12,0)

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

 7장 연습문제

1. 현재 날짜 출력하고 컬럼명은 'Current Date'로 출력하시오


select to_char(sysdate,'yyyy-mm-dd') "Current Date"
from dual;

2. EMP 테이블에서 현재 급여에서 15%증가된 급여를 사원번호, 이름,업무,급여,

  증가된 급여(New Salary), 증가액(Increase)를 출력


select empno,ename,job,sal,round(nvl(sal+sal*0.15,0),0) "인상된 급여",round(nvl(sal*0.15,0),0) "증가액"
from emp;

3. EMP테이블에 이름,입사일,입사일로부터 6개월 후 처음 돌아오는 월요일의 날짜 출력


select ename,hiredate,next_day(add_months(hiredate,6),'monday')
from emp;

4. EMP테이블에서 이름,입사일, 입사일로부터 현재까지의 월수, 총급여, 현재급여 출력

select ename,hiredate,round(months_between(sysdate,hiredate),0) 근무개월수,
       round(months_between(sysdate,hiredate),0)*sal 총월급,
       round(months_between(sysdate,hiredate),0)*(nvl(sal,0)+nvl(comm,0)) 총급여
from emp
order by 5 desc;

5. 다음과 같이 출력하시오.

Dream Salary

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

KING earns   $5,000 monthly but wants   $15,000
SCOTT earns   $3,000 monthly but wants    $9,000
FORD earns   $3,000 monthly but wants    $9,000
JONES earns   $2,975 monthly but wants    $8,925

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

select ename || ' earns' || to_char(sal,'$999,999') || ' monthly but wants ' || to_char(sal*3,'$999,999')
from emp
order by sal desc;

6. EMP테이블에서 모든 사원의 이름과 급여를 출력.

  단, 이름은 15자리로 지정하고, 공백부분은 *로 채워라.


select ename,lpad(to_char(sal,'$9,999'),15,'*')
from emp
order by sal

7. EMP테이블에서 모든 사원의 이름,업무,입사일,입사요일 출력
select ename,job,hiredate,
       case
         when to_char(hiredate,'d') =1 then '일요일'
            when to_char(hiredate,'d')='2' then '월요일'
            when to_char(hiredate,'d')='3' then '화요일'
            when to_char(hiredate,'d')='4' then '수요일'
            when to_char(hiredate,'d')='5' then '목요일'
            when to_char(hiredate,'d')='6' then '금요일'
            when to_char(hiredate,'d')='7' then '토요일'
       end "입사요일"      
from emp;

8. EMP테이블에서 이름이 6글자 이상인 사원의 이름,이름글자수,업무 출력
select ename,length(ename) 이름길이,job
from emp
where length(ename) >= 6
order by ename desc;

9. EMP테이블에서 모든 사원의 정보를 이름,업무,급여,보너스,급여+보너스 출력
select ename,job,sal,nvl(comm,0) 보너스,nvl2(sal+comm,comm,0) "급여+보너스"
from emp
order by 5 desc;

by joon | 2006/10/23 22:30 | Oracle | 트랙백 | 덧글(0)
2006년 10월 23일〃posted title : 데이터 제한 과 정렬

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

-- SQL 연산자

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

* BETWEEN

BETWEEN a AND b

NOT BETWEEN a AND b

select *

from emp

where sal (not) between 1000 and 3000;

--> 1000과 3000은 범위에 포함된다.

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

* IN

IN (list)
NOT in (list)

select *
from emp
where JOB IN ('SALESMAN','CLERK');

--> SALESMAN혹은 CLERK인 데이터

select *
from emp
where JOB='SALESMAN' OR JOB='CLERK'

--> IN구문과 같은 효과를 지니나, 보다 빠른 속도를 지닌다.

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

* LIKE

LIKE
NOT LIKE

select name,jubun
from member
where jubun like '______1%' or jubun like '______3%';

--> 7번째 문자가 '1' 혹은 '3'인것 검색

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

* NULL

IS NULL
IS NOT NULL

select *
from EMP
where comm is null;

--> comm이 null인 데이터 추출

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

* ESCAPE

select *
from jepum
where bigo like '%99.9%%' 

--> 99.9%와 99.9점 모두 출력한다.

select *
from jepum
where bigo like '%99.9/%%' escape '/';  

--> like 연산에서 %를 검색할수  있도록 도와준다.

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

-- ex) 아래의 like문 중에서 index를 검색하는것은....? 

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

     like 's%'
     like '%s'
     like '%s%'
     like '_s%'
     like '3%'
    
  --> 답은 like 's%' 이다.
      첫 글자가 문자인경우에만 인덱스 연산을 하며,
   숫자 혹은 와일드카드(%,_등등.)인 경우 인덱스 연산을 하지 않는다.

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

-- 제 6장. 연습문제

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

2. emp테이블에서 급여가 3000이상인 사원의 정보를 출력하시오.

select empno,ename,job,sal
from EMP
where sal > 3000

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

3. emp테이블에서 사원번호가 7788인 사원의 정보를 출력하시오.

select ename,deptno
from EMP
where empno=7788;

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

4. emp테이블에서 입사일이 February 20,1981과 May 1,1981사이인 사람을
 출력하시오. 단, 입사일 순으로 정렬.

select ename,job,hiredate
from EMP
where to_char(hiredate,'yyyy-mm-dd') between '1981-02-20' and '1998-05-01'
order by 3;

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

5. emp테이블에서 부서번호가 10,혹은 20인 사람의 정보를 출력하시오.   
  단, 이름순으로 정렬.

select *
from EMP
where deptno = 10 or deptno =20
order by ename;

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

6. emp테이블에서 급여가 1500이상이고, 부서번호가 10 혹은 30인 사람의
 정보를 출력하고, Heading을 Employee와 Monyhly Salary로 출력하라.
 
select ename Employee ,sal "Monthly Salary",deptno
from EMP
where sal>=1500 and (deptno=10 or deptno=30)
order by 1;

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

7. emp테이블에서 1982년에 입사한 사원의 모든 정보를 출력하라.

select *
from EMP
where to_char(hiredate,'yyyy') = '1982'

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

8. emp테이블에서 comm이 null이 아닌 사원을 출력하라.

select *
from emp
where comm is not null

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

9. emp테이블에서 보너스가 급여보다 10%이상 많은 사람 출력

select ename,sal,comm
from EMP
where comm > sal+(sal*0.1)

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

10. emp테이블에서 직종이 Clerk이거나 Alalyst이고,
급여가 1000,3000,5000이 아닌 사람을 출력하라

select *
from EMP
where (job='CLERK' or job='ANALYST') and (sal not in(1000,3000,5000))

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

11. emp테이블에서 이름에 'L'이 두 글자 있고, 부서가 30이거나
관리자 번호가 7782인 사람을 출력하라.

select *
from EMP
where (DEPTNO=30 or MGR=7782) and ename like '%L%L%'

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

by joon | 2006/10/23 22:22 | Oracle | 트랙백 | 덧글(0)
2006년 10월 23일〃posted title : SYNONYM(동의어)


시노님은 오라클 객체(테이블, 뷰, 시퀀스, 프로시저)에 대한 대체이름(Alias)를 말합니다.

Synonym은 실질적으로 그 자체가 Object가 아니라 Object에 대한 직접적인 참조 입니다.

시노님을 사용하는 이유는..

데이터베이스의 투명성을 제공하기 위해서 사용 한다고 생각하면 됩니다.
    시노님은 다른 유저의 객체를 참조할 때 많이 사용을 합니다.

② 만약에 실무에서 다른 유저의 객체를 참조할 경우가 있을 때 시노님을 생성해서 사용을 하면은
    추후에 참조하고 있는 오프젝트가 이름을 바꾸거나 이동할 경우 객체를 사용하는 SQL문을 모두
    다시 고치는 것이 아니라 시노님만 다시 정의하면 되기 때문에 매우 편리 합니다.

객체의 긴 이름을 사용하기 편한 짧은 이름으로 해서  SQL코딩을 단순화 시킬 수 있습니다.

또한 객체를 참조하는 사용자의 오브젝트를 감추 수 있기 때문에 이에 대한 보안을 유지할 수
    있습니다
.
   시노님을 사용하는 유저는 참조하고 있는 객체를에 대한 사용자의 object의 소유자, 이름, 서버이름을  모르고 시노님 이름만 알아도 사용 할 수 있습니다.



Synonyms을 사용하는 경우

 - 오브젝트의 실제 이름과 소유자 그리고 위치를 감춤으로써 database 보안을 개선하는데 사용 됩니다
 - Object에의 Public Access를 제공 합니다.
 - Remote Database의 Table, View, Program Unit를 위해 투명성을 제공 합니다.
 - Database 사용자를 위해 SQL 문을 단순화 할 수 있습니다.


시노님에는 두가지 종류가 있습니다.

Private Synonym
   - 전용 시노님은 특정 사용자만  이용할수 있습니다.

Public Synonym
  - 공용 시노님은 공용 사용자 그룹이 소유하며 그Database에 있는 모든 사용자가 공유 합니다.


 시노님 생성 문법(Syntax)




 - PUBLIC : 모든 사용자가 접근 가능한 시노님을 생성 합니다.
                PUBLIC  시노님의 생성 및 삭제는 DBA만이 할 수 있습니다.


 ※ scott USER의 emp테이블을 test USER가 사용 하는 예제.


 1. 먼저 scott/tiger USER로 접속해서 test USER에게 emp테이블을 조작할 권한을 부여합니다.

 SQL>GRANT ALL ON  emp TO  test;
         권한이 부여되었습니다.

         test user에 대하여 scott의 emp테이블을 조작할 수 있는 권한을 부여합니다.
         권한이 있어야 select하거나 update, insert할수 있습니다.



 2. test USER로 접속해 동의어를 생성합니다.

 SQL> connect test/test

 SQL> CREATE SYNONYM  scott_emp FOR  scott.emp ;
         시노님이 생성되었습니다.

          scott USER가 소유하고 있는 emp 테이블에 대해 scott_emp라는 일반시노님을 생성했습니다.
          scott 사용자의 emp테이블을 test 사용자가 scott_emp라는 동의어로 사용 합니다. .

  -- 시노님을 이용한 쿼리
 SQL> SELECT empno,  ename FROM  scott_emp;

 -- 일반 테이블을 쿼리
 SQL> SELECT empno,  ename FROM  scott.emp;
          이 두 쿼리의 결과는 같습니다.

   EMPNO ENAME
-------- ---------
    7369 SMITH
    7499 ALLEN
    7521 WARD
    7566 JONES
    7654 MARTIN
    7698 BLAKE
          15 개의 행이 선택되었습니다.


 동의어 삭제

 SQL> DROP c   scott_emp;
         시노님이삭제되었습니다.

 SQL> SELECT empno,  ename FROM  scott_emp;
         라인 1 에 오류:
         ORA-00942: 테이블 또는 뷰가 존재하지 않습니다
 

  ================================================
    * Oracle Community OracleClub.com
by joon | 2006/10/23 22:13 | Oracle | 트랙백 | 덧글(1)

<< 이전 페이지 | 다음 페이지 >>

카테고리
이글루 파인더
최근 등록된 덧글
여행기는 이제 출처를 ..
by notebook at 01/20
방문겸사겸사 테러하고감..
by sleepyhead at 12/04
돗대기 검색하니까 나오..
by sleepyhead at 12/04
뭘로 할까;;;
by joon at 10/18
여긴 무슨 돗대기 시장도..
by 훈사마 at 10/18
방법은 단순한거다.....
by 훈사마 at 10/18
겨울도 아닌데..썰렁하네
by skyer at 08/07
아무도 오지 않는다....
by joon at 07/06
ms는 언제쯤 망해버릴까?..
by 땡깡쟁이 at 01/29
유비쿼터스의 신호탄이 ..
by 땡깡쟁이 at 01/28
라이프로그
메뉴릿
rss

skin by 서비