카테고리 없음

오라클 - 조인

장꾸꾸 2020. 10. 20. 09:49

조인 : 기존 ㅔㅌ이블에 새로운 테이블을 붙여서 늘려주는 것. / 중복되는 것은 뺌

연습

<inner join>

-- 조인 연습
-- 사원 테이블과 부서테이블을 조인해서 모든 사원을 출력
--사원이름/ 부서이름(department_name) 출력 -> 107건수
--1. Ansi 표준구문
select last_name as 사원이름, department_name as 부서이름
from employees
inner join departments using (department_id);

employee와 department에 공통적으로 들어간 것을 통해 공통적으로 

107개 -> 106개가 되는 것은 kimberly가 부서가 없기 때문. 그림과 같이 제거가 됨.

inner 조인 혹은 조인을 사용하게 되면 공통적 데이터가 있을 때만 연결시켜줌

 

<left join> : 모두를 포함시킴 -> Grant || (null)로 나옴

select last_name as 사원이름, department_name as 부서이름
from employees
left join departments using (department_id);

 

--2.  employee jobs 연결 job id로 연결 / left로 모든 사원추가
select last_name, job_title, salary
from employees
left join jobs using (job_id);

모든 사원이 나오니까 107개 나옴

*** 밑에 꼭 풀어보기 ** : 조인의 순서도 중요

--employees, departments, locations, jobs, regions, countries를 조인해서
--다음과 같이 출력하시오. 모든 사원을 출력하시오 (107건) 
--사원번호 사원이름 업무명 부서이름 근무지역  도시  근무국가
select employee_id, last_name, job_title, department_name, region_name, city, country_name
from employees
left join jobs using(job_id)
left join departments using(department_id)
left join locations using(location_id)
left join countries using(country_id)
left join regions using(region_id);

 

"employee와 location을 연결할 때는 둘 사이에 공통이 없기 때문에 

department를 교각 역할! 중간 department_id가 공통! "

left join departments using(department_id)
left join locations using(location_id)

 

 

 

 

 

test1

★ SQL문
1. 데이타 조작어(DML : Data Manipulation Language)
    : insert, update, delete, merge
2. 데이타 정의어(DDL : Data Definition Language)
    : create, alter, drop, rename, truncate    
3. 데이타검색
    : select 
4. 트랜젝션제어
    : commit, rollback, savepoint
5. 데이타 제어어(DCL : Data Control Language)
    : grant,  revoke

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
[형식]
 select [distinct] [컬럼1,컬럼2,.....][as 별명][ || 연산자][*]
 from 테이블명
 [where 조건절] 

distinct : 중복제거
* : 모든
조건절 : and,or,like,in,between and,is null,is not null
==================================================================================
select * from tab;                -- 테이블 목록확인하기
select * from employees;   --employees테이블의 내용확인하기
select * from departments; 

--ex1)employees테이블의 모든 사원의 사원번호,이름(last_name),급여 검색
select employee_id, last_name, salary 
from employees;

--ex2)employees테이블에서 모든 사원의 이름, 입사일, 업무ID 만 검색
select  last_name, hire_date, job_id 
from employees;

--ex3)employees테이블에서 모든 사원의 이름(last_name), 연봉(salary*12)만 검색
select  last_name, salary*12
from employees;


--ex4)별명붙이기(as는 생략가능)
--    employees테이블의 모든 사원의 사원번호,이름(last_name),급여 검색
--    조건) title 사원번호, 이름 ,급여로 출력할것
select  employee_id as "사원번호", last_name as "이름", salary as "급여"
from employees;

select  employee_id  "사원번호", last_name  "이름", salary  "급여"
from employees;

select  employee_id  사원번호, last_name  "이  름", salary  급여
from employees;

--ex5) employee테이블에서 사원번호,이름,연봉을 구하시오
--     조건1) 연봉 = 급여 * 12
--     조건2) 제목을 사원번호, 이름,연봉으로 출력
select employee_id as "사원번호",last_name as "이  름",salary*12 as "연 봉"
from employees;

--ex6) 연결연산자( || ) : 컬럼을 연결해서 출력
--    first_name과  last_name을 연결해서 출력하시오
--     이   름
--     ------------
--     Ellen   Abel
select first_name ||  '    '   || last_name as "이  름"
from employees;

--ex7) 다음처럼 출력하시오
--   사원번호    이  름        연 봉
--   ---------------------------------------------
--    100      Steven King   288000달러 
select employee_id as "사원번호", first_name || '  ' || last_name as  "이 름",
          salary * 12 || '달러' as "연 봉"
from employees;

--ex8) 다음처럼 출력하시오 (last_name, job_id이용)
--     Employee  Detail
--     --------------------
--     King  is a  AD_PRES
select last_name || ' is a ' || job_id as "Employee Detail"
from employees;

--중복제거(distinct)
--ex9)employees테이블에서 부서를 출력하시오
--    조건1)중복되는 부서는 1번만 출력하시오
--    조건2)부서별 오름차순으로 보여주시오
select distinct  department_id
from employees
order by department_id asc;     -- desc(내림차순)

--ex10) 10번부서 또는 90번부서 사원들의 이름,입사일,부서ID를 출력하시오
select last_name, hire_date, department_id
from employees
where department_id=10  or department_id=90;

--ex11)급여가 2500이상 3500미만인 사원의 이름(last), 입사일, 급여를 검색하시오
select last_name, hire_date, salary
from employees
where salary>=2500 and salary<3500;


--ex12) 급여가 2500이하 이거나 3000이상이면서, 90번 부서인 사원의 이름, 급여, 부서ID를 출력하시오.
--      조건1) 제목은 사원명, 월  급, 부서코드로 하시오
--      조건2) 급여앞에 $를 붙이시오
--      조건3) 사원명은 first_name과 last_name을 연결해서 출력하시오
select first_name || '  ' || last_name as "사원명",
         '$' || salary as "월 급", department_id as "부서 코드"
from employees
where (salary<=2500 or salary>=3000) and department_id=90;
   
--ex13) 'King'사원의 모든 컬럼을 표시하시오
select * 
from employees
where last_name='King';   -->문자열검색할때 대.소문자를 구분

SELECT *
FROM EMPLOYEES
WHERE UPPER(LAST_NAME)='KING';   --->문자열을 대문자로

SELECT *
FROM EMPLOYEES
WHERE LOWER(LAST_NAME)='king';   --->문자열을 소문자로

-- like  : 문자를 포함
-- '%d'      d로 끝나는 
-- 'a%'      a로 시작하는
-- '%test%'   test가 포함되어있는
-- 예)  select * from employees where first_name like '%net%';
--ex14)업무ID에 CL이 포함되어있는 사원들의 이름,업무ID,부서ID를 출력하시오  --45건
select last_name, job_id, department_id
from employees
where job_id like '%CL%';

--ex15) 업무ID가  IT로 시작하는 사원들의 이름,업무ID,부서ID를 출력하시오  -- 5건
select last_name, job_id, department_id
from employees
where job_id like 'IT%';

--ex16) is null / is not null 
--커미션을 받는 사원들의 이름과 급여,커미션을 출력하시오 -- 35건
select last_name, salary, commission_pct
from employees
where commission_pct is not null;

--ex17)커미션을 받지 않는 사원들의 이름과 급여,커미션을 출력하시오 -- 72건
select last_name, salary, commission_pct
from employees
where commission_pct is null;

--ex18) in연산자(or연산자의 다른표현)
--업무ID가  FI_MGR이거나  FI_ACCOUNT인 사원들의 사원번호,이름,직무를 출력하시오   --6건

--방법1
select employee_id,last_name,job_id
from employees
where job_id='FI_MGR' or job_id='FI_ACCOUNT';

--방법2
select employee_id,last_name,job_id
from employees
where job_id in('FI_MGR','FI_ACCOUNT');

ex19) between연산자(and연산자의 다른 표현) : 초과,미만에서는 사용할수 없다
--급여가  10000이상  20000이하인 사원의 사원번호,이름,급여를 출력하시오   --18건

--방법1
select employee_id, last_name, salary
from employees
where (salary<=20000 and salary>=10000)

--방법2
select employee_id, last_name, salary
from employees
where salary between 10000 and 20000

--[문제1] 업무ID가 'SA_REP' 이거나 'AD_PRES' 이면서, 급여가 15000를 초과하는 
--사원들의 이름,업무ID,급여를 출력하시오
--이름        업무ID            급  여
-- --------------------------------------
--King       AD_PRES            24000원

select last_name as 이름, job_id as 업무ID, salary||'원' as "급    여"
from employees
where job_id in ('AD_PRES', 'SA_REP') and salary>15000
------------------------------------------------------------------------------
--[문제2] Employees테이블의 업무ID가 중복되지 않게 표시하는 질의를 작성하시오
-- JOB_ID
-- ---------
--AC_ACCOUNT
--AC_MGR
--     :

select distinct job_id
from employees
order by job_id asc;
-----------------------------------------------------------------------------
--[문제3] 입사일이 03년인 사원들의 사원번호,이름,입사일을 표시하시오
select employee_id, last_name, hire_date
from employees
where hire_date like '03%' 

select employee_id 사원번호, last_name 이름, hire_date 입사일 
from employees 
where hire_date not like '03%' and hire_date not like '%03' and hire_date like '%03%';

 

test2

[연산자]
=  : 같다
!=,  ^=,  <> : 같지않다
>=, <=, >, < : 크거나같다,작거나같다,크다,작다
and, or, between and, in, like, is null/is not null

※ select 
select  [distinct] [컬럼1, 컬럼2.......][*][ ||연결연산자][as 별명]
from 테이블명
[where 조건절]
[order by 컬럼명 asc|desc ]   --asc는 생략가능

order by : 정렬
         asc  - 오름차순(생략가능)
         desc - 내림차순
컬럼명 : 숫자로도 가능
=======================================================================================
--ex1) 사원명,부서ID,입사일을 부서별로 내림차순 정렬하시오
select last_name, department_id, hire_date
from employees
order by 2 desc;    -- order by department_id desc;

--ex2) 사원명, 부서ID, 입사일을  부서별로 내림차순 정렬하시오
--     같은부서가 있을때는  입사일순으로 정렬하시오
select last_name, department_id, hire_date
from employees
order by 2 desc, 3;        -- order by department_id desc, hire_date asc;

--ex3) 사원들의 연봉을 구한후 연봉순으로 내림차순정렬하시오   
--이 름     연 봉     
-- ---------------
--King      28800

select  last_name as "이름", salary*12 || '달러' as "연봉"
from employees
order by  salary desc;
=======================================================================================
[단일행 함수]
1. 숫자함수 : mod(나머지), round(반올림), trunc(내림), ceil(올림) 
2. 문자함수 : lower, upper, length, substr, ltrim, rtrim, trim
3. 날짜함수 : sysdate, add_month, month_between
4. 변환함수
   (1) 암시적(implict)변환:자동
       VARCHAR2 또는 CHAR    ------>     NUMBER
       VARCHAR2 또는 CHAR    ------>     DATE
       NUMBER               ------>     VARCHAR2
       DATE                 ------>     VARCHAR2   

    (2) 명시적(explict)변환:강제
    
            TO_NUMBER      TO_DATE
            <------        ------>
     NUMBER       CHARACTER        DATE
            ----->         <------
            TO_CHAR        TO_CHAR

-날짜형식-
YYYY : 네자리연도(숫자)         (ex.  2005)  
YEAR : 연도(문자)
MM : 두자리 값으로 나타낸 달    (ex.   01, 08, 12)
MONTH : 달 전체이름             (ex.   January) 
MON : 세자리 약어로 나타낸 달   (ex.   Jan)  
DY : 세자리 약어로 나타낸 요일  (ex. Mon) 
DAY : 요일전체                  (ex. Monday) 
DD : 숫자로 나타낸 달의 일      (ex. 31, 01) 

-숫자형식-
9 : 숫자를 표시
0 : 0을 강제로 표시
$ : 부동$기호를 표시
L : 부동 지역통화기호 표시(한국,일본...)
.  : 소수점출력
,  : 천단위 구분자 출력

5. 그룹(집합)함수 : avg, sum, max, min, count
6. 기타함수 : nvl, dcode, case
=======================================================================================
--ex1)  이름을 소문자로 바꾼후 검색
--'Higgins'사원의 사원번호,이름,부서번호를 검색하시오
select employee_id, last_name, department_id
from employees
where lower(last_name)='higgins';

--ex2) 10을 3으로 나눈 나머지 구하시오(mod)
select mod(10,3) from dual;        --dual:가상 테이블

--ex3) 35765.357을 반올림(round)
select round(35765.357, 2) from dual;       <---35765.36
select round(35765.357, 0) from dual;       <---35765
select round(35765.357, -3) from dual;      <---36000 

--ex4) 35765.357을 내림(trunc)
select trunc(35765.357, 2) from dual;       <---35765.35
select trunc(35765.357, 0) from dual;       <---35765
select trunc(35765.357, -3) from dual;      <---35000 

select ceil(35765.357) from dual;       <--- 35766 (ceil은 정수만 가능)

--ex5) concat('문자열1','문자열2') : 문자열의 결합(문자열1+문자열2)
select concat('Hello',' World') from dual;    <--- Hello World

--ex6) length('문자열')  : 문자열(캐릭터)의 길이
--     lengthb('문자열') : 문자열(BYTE)의 길이
  
--     사용예)  엘리트 , 엘리트
--                          char(20)           varchar2(20)
--           length           14                  3            <---- 엘리트
--           lengthb          20                  9            <---- 엘리트


--     사용예)  elite , elite
--                          char(20)           varchar2(20)
--           length           20                  5             <---- elite
--           lengthb          20                  5             <---- elite

create table text (str1 char(20),str2 varchar2(20));
insert into text(str1,str2) values('엘리트','엘리트');
insert into text(str1,str2) values('elite','elite');
commit;

select * from tab;
select * from text;
select length(str1),length(str2) from text where str1='엘리트';     --14   3
select lengthb(str1),lengthb(str2) from text where str1='엘리트';    --20   9

select length(str1),length(str2) from text where str1='elite';     --20   5
select lengthb(str1),lengthb(str2) from text where str1='elite';   --20   5

--ex7) 
select length('korea') from dual;       <----5
select length('코리아') from dual;      <----3
select lengthb('korea') from dual;      <----5
select lengthb('코리아') from dual;     <----9


--ex8) 지정한문자열찾기 : instr(표현식,찾는문자,[위치]) 1:앞(생략가능), -1:뒤
select  instr('HelloWorld','W') from dual;               <---6
select  instr('HelloToWorld','o', -5) from dual;         <---7 

--ex9) 지정한 길이의 문자열을 추출 : substr(표현식,시작,[갯수])
select  substr('I am very happy', 6, 4) from dual;      <--- very
select  substr('I am very happy', 6) from dual;         <--- very happy

--ex10) employees 테이블에서 조건에 맞게 검색하시오(concat,  length)   -- 19레코드
--      조건1) 이름과 성을 연결하시오(concat)
--      조건2) 구해진 이름의 길이를 구하시오(length)
--      조건3) 성이 n으로 끝나는 사원(substr)

--employee_id        name           length
-- -----------------------------------------------
--  102              LexDe Haan       10
select employee_id, concat(first_name,last_name) as "name", 
         length(concat(first_name,last_name)) as "length"
from employees 
where substr(last_name,-1,1)='n';

--ex11) 임의의 값이 지정된 범위내에 어느위치 : width_bucket(표현식,최소값,최대값,구간)
--최소-최대값을 설정하고 10개의 구간을 설정후 위치찾기
--0-100까지의 구간을 나눈후 74가 포함되어있는구간을 표시하시오
select width_bucket(74,0,100,10) from dual;  -- 8
 
--ex12) 공백제거 : ltrim(왼), rtrim(오른), trim(양쪽)
select rtrim('test    ') || ltrim('   exam') from dual;

--ex13) sysdate : 시스템에 설정된 시간표시
select sysdate from dual;
select to_char(sysdate,'YYYY"년" MM"월" DD"일"')as 오늘날짜 from dual;

select to_char(to_date('15/01/05'),'YYYY"년"fmMM"월"DD"일"') from dual;   
-- 2015년 1월 5일

select to_char(to_date('15/01/05'),'YYYY"년"fmMM"월"fmDD"일"') from dual;   
-- 2015년 1월 05일

--ex14) add_months(date, 달수):날짜에 달수 더하기
select add_months(sysdate,7) from dual;

--ex15) last_day(date) : 해당달의 마지막날
select last_day(sysdate) from dual;         <---- 2020-10-31
select last_day('2004-02-01') from dual;    <---- 2004-02-29
select last_day('2005-02-01') from dual;    <---- 2005-02-28

--ex16) 오늘부터 이번달 말까지 총 남은 날수를 구하시오
select last_day(sysdate)-sysdate from dual;

--ex17) months_between(date1,date2) : 두 날짜사이의 달수
select round(months_between('2014-02-10','2013-10-21')) from dual;

--ex18) 암시적인 변환(자동)
desc employees;             -- employees의 구조확인

select employee_id,last_name 
from employees
where department_id='90';   <---        number --> varchar2(자동 변환)

select months_between('15-10-21','14-10-20') from dual;   <----12.033333
                      -- date --> number(자동 변환)

--ex19) 명시적인 변환(강제)     number --> character
select last_name, salary
from employees
where last_name='King';

select last_name, to_char(salary,'$99,999.00')
from employees
where last_name='King';

--ex20) fm형식 : 형식과 데이터가 반드시 일치해야함(fm - fm사이값만 일치)
select  last_name,hire_date   from employees   where hire_date='05/06/25';   --05/06/25
select  last_name,hire_date   from employees   where hire_date='05/6/25';     --05/06/25

select  last_name,hire_date   from employees where last_name='Austin';

select  to_char(to_date('15-04-07'),'YYYY-MM-DD') from dual;       --2015-04-07
select  to_char(to_date('15-04-07'),'YYYY-fmMM-DD') from dual;     --2015-4-7
select  to_char(to_date('15-04-07'),'YYYY-fmMM-fmDD') from dual;   --2015-4-07   

--ex)2007-02-07에 입사한 사원을 검색하시오
select * from employees where hire_date='07/02/07';             ==> 결과 나옴

select * 
from employees
where to_char(hire_date,'YY-MM-DD')                                          
        =to_char(to_date('07/02/07','YY-MM-DD'),'YY-fmMM-DD');   ==> 결과 안나옴(07/02/07 = 07/2/7)           


--ex21) RR, YY형식

   (반환일:현재년도의 세기)                  지정한연도(뒤 두자리)
                                -----------------------------------------------------
                                    0 - 49              0 - 99     
   ===================================================================================
   현재연도 (뒤 두자리)    0 - 49     반환일의 현재세기       반환일의 이전세기
                      ----------------------------------------------------------
                      50 - 99     반환일의 다음세기      반환일의 현재세기


   예)  현재년도            지정한날짜          RR형식            YY형식
        -----------------------------------------------------------------
           1995          27-oct-95               
           1995          27-oct-17               
           2001          27-oct-17               
           2001          27-oct-95               

select  to_char(to_date('97/9/30','YY-MM-DD'),'YYYY-MM-DD') from dual; <--2097
select  to_char(to_date('97/9/30','RR-MM-DD'),'RRRR-MM-DD') from dual; <--1997
select  to_char(to_date('57/9/30','YY-MM-DD'),'YYYY-MM-DD') from dual; <--2057
select  to_char(to_date('57/9/30','RR-MM-DD'),'RRRR-MM-DD') from dual; <--1957

--ex22)
select to_char(to_date('97/9/30'), 'YYYY-MON-DD') from dual;
select to_char(to_date('9/30/97','MM-DD-YY'), 'YYYY-MON-DD') from dual;  <--2097
select to_char(to_date('9/30/97','MM-DD-RR'), 'RRRR-MON-DD') from dual;  <--1997

--ex23)2005년 이후에 고용된 사원을 찾으시오
--last_name     hire_date
------------------------------------
--King           17-Jan-1987
--Kochhar        21-sep-1989
--Whalen         17-sep-1987

select last_name,to_char(hire_date,'dd-mon-yyyy')
from employees
where hire_date>=to_char(to_date('2005-01-01','yy-mm-dd'),'yy-mm-dd');
                     
select last_name,to_char(hire_date,'yyyy-mm-dd')
from employees
where hire_date>='2005-01-01';

--**그룹함수    
--ex24) count(컬럼명), max(컬럼명), min(컬럼명),avg(컬럼명),sum(컬럼명) 함수
--employees테이블에서 급여의 최대,최소,평균,합을 구하시오
--조건) 평균은 소수이하절삭,합은 세자리마다 콤마찍고 \표시
select count(*), max(salary), min(salary),
       trunc(avg(salary),0), to_char(sum(salary), 'L99,999,999')
from employees;

--ex25) 커미션을 받지 않는 사원의 인원수를 구하시오
select count(*)
from employees
where commission_pct is null;

--ex26) employees테이블에서 없는 부서 포함해서 총 부서의 수를 구하시오(답 : 12개)
--      (nvl사용) 
select count(distinct nvl(department_id,1000))
from employees;

select distinct department_id from employees;
select count(distinct department_id) from employees;
select distinct nvl(department_id,1000) from employees;   <--- nvl은 null값인 경우 1000으로 대치

--문제) 다음조건을 출력하시오
--        조건1) 사원이름, 급여, 커미션, 연봉을 출력하시오
--        조건2) 연봉 = 급여*12 + (급여*12)*커미션으로 한다
--        조건3) 커미션을 받지 않는경우에는 0으로 표시한다
select last_name as "사원이름", 
       salary as "급여",
       nvl(commission_pct,0) as "커미션",
       salary * 12 + (salary*12) * nvl(commission_pct,0) as "연봉"
from employees;  

select last_name as "사원이름", 
       salary as "급여",
       commission_pct as "커미션",
       salary*12+(salary*12) * commission_pct as "연봉"
from employees; 

--ex27) ① decode(표현식,검색1,결과1,검색2,결과2....[default])
--           : 표현식과 검색을 비교하여 결과 값을 반환 다르면 default
--      ② case  [value]  when  표현식  then  구문1
--                       when  표현식  then  구문2
--                                        :
--                       else  구문3
--        end

--ex28)업무 id가 'SA_MAN'또는'SA_REP'이면 'Sales Dept' 그 외 부서이면 'Another'로 표시
--조건) 분류별로 오름차순정렬
--        직무          분류
--       --------------------------
--       SA_MAN    Sales Dept
--       SA_REP      Sales Dept
--       IT_PROG    Another

--방법1
select job_id as "직무",
       decode(job_id,'SA_MAN','Sales Dept','SA_REP','Sales Dept','Another') as "분류"
from employees
order by 2;

--방법2
select job_id as "직무",
	   case job_id when 'SA_MAN' then 'Sales Dept'
	               when 'SA_REP' then 'Sales Dept'
	               else 'Another'
       end as "분류"
from employees
order by 2;
               --힌트) case when salary<10000 then '초급'
--ex28) 급여가 10000미만이면 초급, 20000미만이면 중급 그 외이면 고급을 출력하시오 
--      조건1) 컬럼명은  '구분'으로 하시오
--      조건2) 제목은 사원번호, 사원명, 구  분
--      조건3) 구분(오름차순)으로 정렬하고, 구분값이 같으면 사원명(오름차순)으로 정렬하시오
select employee_id as "사원번호", last_name as "사원명",
       case when salary<10000 then '초급'
            when salary<20000 then '중급'
            else '고급'
       end  as "구분"
from employees
order by 3, 2;

--rank함수 : 전체값을 대상으로 순위를 구함
--rank(표현식) within group(order by 표현식)     ---> 부분
--rank() over(쿼리파티션)                        ---> 전체순위를 표시

--ex29)급여가 3000인 사람의 상위 급여순위를 구하시오
select rank(3000) within group(order by salary desc) "rank"
from employees;

--ex30)전체사원의 급여순위를 구하시오
select employee_id,salary, rank() over(order by salary desc) "rank" 
from employees;

--first_value함수 : 정렬된 값 중에서 첫번째값 반환
--first_value(표현식) over(쿼리파티션)

--ex31)전체사원의 급여와 함께 각부서의 최고급여를 나타내고 비교하시오
select employee_id,salary,
       first_value(salary) over(partition by department_id order by salary desc)
       "부서별최고급여", department_id
from employees
order by department_id asc;

select employee_id,salary,
       first_value(salary) over(partition by department_id order by salary)
       "부서별최저급여", department_id
from employees
order by department_id asc;

--ex32)업무ID가 'ST_CLERK' 또는 'SA_REP'인 직무인 사원들의 급여와 함께 각 업무ID의 최저급여를 나타내고 비교하시오
-- employee_id  job_id  업무ID별최저급여   salary
-- ----------------------------------------------
--173	        SA_REP       	6100	 6100
--179           SA_REP	        6100	 6200
--167	        SA_REP	        6100	 6200
--166	        SA_REP     	    6100	 6400

select employee_id, job_id,
       first_value(salary) over(partition by job_id order by salary)
       "업무ID별 최저급여", 
       salary
from employees
where job_id in('ST_CLERK', 'SA_REP')
order by job_id asc;
===========================================================================================
--[문제1] 사원테이블에서 사원번호, 이름, 급여, 커미션, 연봉을 출력하시오
--        조건1) 연봉은 $ 표시와 세자리마다 콤마를 사용하시오
--        조건2) 연봉 = 급여 * 12 + (급여 * 12 * 커미션) 
--        조건3) 커미션을 받지 않는 사원도 포함해서 출력하시오
select employee_id as "사원번호",last_name as "사원이름",
         salary as "급여", nvl(commission_pct,0) as "커미션",
         to_char((salary*12+(salary*12*nvl(commission_pct,0))),
        '$9,999,999') as "연봉"
from employees; 


--[문제2] 매니저가 없는 사원의 매니저 id를, 1000으로 표시
--        조건1) 제목은 사원번호,이름,매니저ID
--        조건2) 모든 사원을 표시하시오       
--                사원번호     이름       매니저ID
--	          ---------------------------------
--	           100           King        1000 
select employee_id as "사원번호",
         last_name as "이름",
         nvl(manager_id,1000) as "매니저ID"
from employees; 

--[문제3] 급여가  7000이상이면 '고급'  3000이상이면 '중급'  3000미만이면 '초급'을 출력
--          grade별로 오름차순 정렬하시오  
--                last_name        salary       grade
--              --------------------------------------------
--                 King               24000      고급
select last_name, salary, 
        case when salary>=7000  then '고급'
             when salary>=3000  then '중급'
             else '초급'
        end as "grade"
from employees
order by 3;



 

test3

※ select 
select [distinct] [컬럼1,컬럼2,.....][as 별명][ || 연산자][*]  --- 6
from 테이블명     --- 1
[where 조건절]    --- 2
[group by컬럼명]  --- 3
[having 조건절]   --- 4
[order by 컬럼명 asc|desc ]  --- 5

group by : 그룹함수(max,min,sum,avg,count..)와 같이 사용
having : 묶어놓은 그룹의 조건절
==================================================================================
--ex1) 사원테이블에서 급여의 평균을 구하시오
--     조건)소수이하는 절삭,세자리마다 콤마(,)
--     사원급여평균
--     ------------
--            6,461
select to_char(trunc(avg(salary)),'99,999') as "사원급여평균"
from employees;

--ex2) 부서별로 급여평균을 구해서 부서ID, 급여평균을 출력하시오
select department_id as "급여평균", to_char(trunc(avg(salary)),'99,999') as "사원급여평균"
from employees
group by department_id
order by department_id;

--ex3) 업무ID별 급여의 합계를 구해서 업무ID, 급여합계를 출력하시오
select job_id as "급여평균", to_char(sum(salary),'99,999,999') as "사원급여합계"
from employees
group by job_id
order by job_id;

--ex4) 부서별 급여평균을 구해서 사원명,부서별 급여평균을 출력하시오 (X)
select last_name, avg(salary)
from employees
group by department_id;

select department_id, avg(salary)
from employees
group by department_id;

--ex5) group by / having절
-- 부서별 급여평균을 구해서 평균급여가  6000이상인 부서만 출력  (8건)
-- (평균급여는 소수점 이하 절삭)
--      부서ID   평균급여
--     -----------------------
--        100       8600
select department_id  as "부서ID", trunc(avg(salary)) as "평균급여"
from employees
group by department_id
having avg(salary) >= 6000
order by 1;

--ex6)부서별 급여평균을 구하시오 (9건)
--    조건1) 소수이하는 반올림
--    조건2) 세자리마다콤마, 화페단위 ₩를 표시
--    조건3)  부서코드        평균급여
--           ---------------------------
--             10              ₩8,600
--    조건4) 부서별로 오름차순정렬하시오 
--    조건5) 평균급여가 5000이상인 부서만 표시하시오
select  department_id as "부서코드",
          to_char(round(avg(salary),0),'L99,999,999') as "평균급여"
from employees  
group by department_id
having avg(salary)>=5000
order by department_id asc; 

--ex7) 비효율적인 having절
--10과 20 부서에서 최대급여를 받는사람의 급여를 구하시오, 부서별로 오름차순 정렬하시오
--department_id     max_salary
-----------------------------
-- 10                    4400
-- 20                    13000 

--(효율적방법)
select department_id, max(salary) as "max_salary"
from employees
where department_id in(10,20)
group by department_id
order by department_id;

--(비효율적방법)
select department_id, max(salary) as "max_salary"
from employees
group by department_id
having department_id in(10,20)
order by department_id;

--ex8) having절 (where + group by + having)
--10과 20 부서에서 최대급여를 받는사람의 급여를 구하시오.  --1건
--[조건1] 부서별로 오름차순 정렬하시오
--[조건2] 최대급여가 5000이상인 부서만 출력하시오
--         department_id     max_salary
--         -----------------------------------
--           20                    13000 
select department_id, max(salary) as "max_salary"
from employees
where department_id in(10,20)
group by department_id
having max(salary)>=5000
order by 1;

--ex9) 20~80번 부서별로  급여를 가장 적게 받는 사원의 급여를 출력하시오 --7건
--      부서별 오름차순으로 할것
--      [출력]    department_id     min_salary

--(효율적방법)
select department_id, min(salary) as "min_salary"
from employees
where department_id between 20 and 80
group by department_id
order by 1;

select distinct department_id, 
       first_value(salary) over(partition by department_id order by salary)
from employees
where department_id between  20 and 80
order by department_id;

--(비효율적방법)
select department_id, min(salary) as "min_salary"
from employees
group by department_id
having department_id between 20 and 80
order by 1;

=======================================================================================
[조인(join)]

(employees)           (departments)                (join)
사       부                부        부              사     부    부
원       서    +           서        서     =        원     서    서
이       번                번        이              이     번    이
름       호                호        름              름     호    름

※종류
0. natural join(자연조인) : 같은컬럼이 여러개 있을때 같은 컬럼 모두를 and 연산해서 연결
1. Inner join(내부조인) : 같은것 끼리만 연결
2. Outer join(외부조인) : 한쪽을 기준(모두포함)해서 연결
                           left  join : 왼쪽컬럼 모두포함
                           right join : 오른쪽컬럼 모두포함
3. full join : 왼쪽,오른쪽 모두 포함
4. self join : 자기자신 테이블과 연결
5. cross join : 모든 경우의 수로 연결
6. non equijoin : 범위에 속하는지 여부를 확인
7. n개 테이블 조인 : 여러개의 테이블 조인

※방법
1. 오라클 구문전용
2. Ansi표준구문

select * from employees;    --107 (부서없는 사원 1명)
select * from departments;  --27

--ex1) inner join : 같은것끼리만 조인
--사원테이블과 부서테이블에서 부서가 같을경우 사원번호,부서번호,부서이름을 출력하시오  -- 106건

--방법1(오라클전용구문)
select employee_id, employees.department_id, department_name
from employees , departments
where employees.department_id=departments.department_id;

--방법2(오라클전용구문)
select employee_id, e.department_id, department_name
from employees e, departments d
where e.department_id=d.department_id;

--방법3(Ansi표준)
select employee_id, department_id, department_name
from employees
inner join departments using(department_id);

--ex2)부서테이블과 위치테이블을 연결하여 부서가 위치한 도시를 알아내시오(inner join)
--     (departments, locations)
--  department_id     city
----------------------------------
--  10                   Seattle

select * from departments;
select * from locations;

--오라클표준
select department_id, city
from departments d, locations l
where d.location_id = l.location_id;

--Ansi표준
select department_id, city
from departments
join locations using(location_id);

--ex3) outer join(left) : 왼쪽 테이블은 모두포함하여 조인
--사원테이블과 부서테이블에서 부서번호가 같은 사원을 조인하시오 ==> 107레코드
--조건 1) 사원이름, 부서ID, 부서이름을 출력하시오
--조건 2) 사원테이블의 모든 사원을 포함하시오

--방법1(오라클전용구문)
select last_name, e.department_id, department_name
from employees e, departments d
where e.department_id=d.department_id(+);

--방법2(ansi표준)
select last_name, department_id, department_name
from employees
left join departments using(department_id);

--ex4) outer join(right) : 오른쪽 테이블은 모두포함하여 조인
--사원테이블과 부서테이블에서 부서번호가 같은 사원을 조인하시오 ===> 122레코드
--조건 1) 사원이름, 부서ID, 부서이름을 출력하시오
--조건 2) 부서테이블의 모든 부서를 포함하시오

--방법1(오라클전용구문)
select last_name, e.department_id, department_name
from employees e, departments d
where e.department_id(+)=d.department_id;

--방법2(ansi표준)
select last_name, department_id, department_name
from employees
right join departments using(department_id);

--ex5) full join : 왼쪽,오른쪽 테이블을 모두포함하여 조인
--사원테이블과 부서테이블에서 부서번호가 같은 사원을 조인하시오 ===> 123레코드
--조건 1) 사원이름, 부서ID, 부서이름을 출력하시오
--조건 2) 사원데이블의 모든사원과 부서테이블의 모든 부서를 포함하시오

--방법1(오라클전용구문)
  X

--방법2(ansi표준)
select last_name, department_id, department_name
from employees
full join departments using(department_id);


select * from departments;
select * from locations;
--ex6) departments 와  locations 자연조인의 비교(같은컬럼 : location_id)  ==> 27레코드
--     두개의 테이블을 연결해서 부서위치(location_id), 도시(city), 부서이름(department_name)을 출력하시오

--방법1(natural  join)
select location_id, city, department_name
from departments
natural join locations;

--방법2(inner join)
select location_id, city, department_name
from departments
join locations using(location_id);

--ex7) inner join,  natural join : 두개의 컬럼이 일치하는경우
--        부서ID와 매니저ID가  같은 사원을 연결하시오
--       (관련테이블 : departments, employees)  : 32 레코드

--        last_name     department_id   manager_id
--        ------------------------------------------

--방법1(오라클전용구문)
select last_name,e.department_id,e.manager_id
from employees e, departments d 
where e.department_id=d.department_id and e.manager_id=d.manager_id

--방법2(ansi표준)
select last_name,department_id,manager_id
from employees
join departments using(department_id,manager_id);

--방법3(natural조인이용)
select last_name,department_id,manager_id
from employees
natural join departments;

--ex8) 내용은 같은데 컬럼명이 다른경우에 조인으로 연결하기
--       departments(location_id) , locations2(loc_id)
        
--      부서ID    부서명             도시
--      -----------------------------------------------------
--      60	      IT	             Southlake
--      50	     Shipping	         South San Francisco
--      10	     Administration	     Seattle

create table locations2 
as select * from locations;     -- 테이블복사

select * from tab;
select * from locations2;

alter table locations2 rename column location_id to loc_id;   
--location_id를 loc_id로 변경

--방법1(오라클표준)
select department_id, department_name, city
from departments d, locations2 l
where d.location_id = l.loc_id;

--방법2(Ansi표준)
select department_id, department_name, city
from departments
join locations2 on(location_id = loc_id);

--ex9) self 조인 : 자기자신의 테이블과 조인하는경우
--        사원과 관리자를 연결하시오, 모든 사원을 표시하시오

--        사원번호   사원이름      관리자
--        ----------------------------------
--        101      Kochhar      King   

--방법1(오라클표준)
select e.employee_id as "사원번호", e.last_name as "사원이름", m.last_name as "관리자"
from employees e, employees m
where e.manager_id = m.employee_id(+);

--방법2(Ansi표준)
select e.employee_id as "사원번호", e.last_name as "사원이름", m.last_name as "관리자" 
from employees e
left join employees m on(e.manager_id=m.employee_id);

--ex10) cross join: 모든행에 대해 가능한 모든조합을 생성하는 조인
select count(*) from countries;     -- 25
select count(*) from locations;     -- 23

select * from countries; 
select * from locations; 

--방법1(오라클표준)
--행수변경 : 도구->환경설정->데이터베이스->고급->SQL배열 인출크기 : 200
select * from countries,locations;  <--- 575 레코드

--방법2(Ansi표준)
select * 
from countries
cross join locations;

--ex11) Non Equijoin (넌 이큐조인) 
--        : 컬럼값이 같은경우가 아닌 범위에 속하는지 여부를 확인할때
--        [형식]  on ( 컬럼명 between 컬럼명1 and 컬럼명2)

create table salgrade(
salvel varchar2(2),
lowst number,
highst number);

insert into salgrade values('A',20000,29999);
insert into salgrade values('B',10000,19999);
insert into salgrade values('C',0,9999);
commit;

select * from salgrade;
select * from tab;

--ex12) 자신이 받는 급여가 어느등급인지를 확인하시오
--    조건1) 타이틀은 사원이름, 급여, 급여등급
--    조건2) 급여별 내림차순으로 정렬하시오
--           사원이름       급여      급여등급
--           ------------------------------------
--            King	       24000	 A
--            De Haan      17000	 B
select last_name as "사원이름", salary as "급여", salvel as "등급"
from employees
left join salgrade on(salary between lowst and highst)
order by 2 desc;

--ex13) n(여러)개의 테이블은 조인
--업무ID같은 사원들의 사원이름,업무내용,부서이름을 출력하시오
--(employees, jobs, departments테이블을 조인)

--[분석]
--employees           jobs            departments
----------------------------------------------------
--department_id      job_id          department_id
--job_id

--[조건]
--1. 부서이름 정렬후 같은 부서이름인 경우 업무명으로 오름차순 정렬하시오
--2. 사원이름, 부서이름, 업무명의 이름으로 출력하시오

--[출력]
--사원이름      부서이름                 업무명    ===> employees   departments   jobs
----------------------------------------------------
--Higgins	Accounting Manager	 Accounting
--Gietz		Public Accountant	 Accounting

select last_name as "사원이름", department_name as "부서이름", job_title as "업무명"
from employees
left join departments using(department_id)
left join jobs using(job_id)
order by 2, 3;

------------------------------------------------------------------------------------
--[문제1] manager_id가 같은 사원을 조인하여 
--        이름(last_name), 부서이름, 매니저ID를 출력하시오   -4건
--        (관련테이블 : employees, departments)

--  조건1)부서이름이 IT인 사원만 출력하시오
--  조건2)이름별로 오름차순 출력하시오
--  조건3)Ansi표준, 오라클 표준을 이용하여 join하시오

--  이름   부서이름   매니저ID
--  ----------------------------
--Austin	IT	103
--Ernst	IT	103
--Lorentz	IT	103
--Pataballa	IT	103
select last_name as "이름", department_name as "부서이름", manager_id as "매니저ID"
from employees
join departments  using(manager_id)
where department_name='IT'
order by last_name asc;

select last_name as "이름", d.department_name as "부서이름", e.manager_id as "매니저ID"
from employees e,departments d
where e.manager_id=d.manager_id and department_name = 'IT'
order by last_name;

------------------------------------------------------------------------------------
--[문제2] 부서테이블과 위치테이블을 조인하여 도시를 알아내시오   --21건
--        (관련테이블 : departments, locations)

--조건1) 도시가 'Seattle'만 출력하시오
--조건2) 부서ID별 내림차순 정렬하시오

-- department_id      city
-- -----------------------------
-- 10                      Seattle

select * from locations;
select * from departments;

select department_id, city
from departments
join locations using (location_id)
where city = 'Seattle'
order by 1 desc;

select d.department_id, l.city
from departments d, locations l
where d.location_id = l.location_id and city = 'Seattle'
order by 1 desc;


------------------------------------------------------------------------------------
--[문제3] 부서번호가 같은 사원을 Ansi표준으로 조인하시오  --9건
--        (관련테이블 : departments, employees)
--  조건1) 타이틀은  사원이름(last_name), 부서ID, 부서이름으로 출력하시오
--  조건2) 부서번호가 30번 또는 90번인 사원들만 출력하시오
--  조건3) 사원이름별 오름차순 정렬하시오
select last_name as "사원이름", d.department_id as "부서ID", department_name as "부서이름"
from departments d, employees e
where e.department_id = d.department_id and d.department_id in(30, 90)
order by 1;

select last_name as "사원이름", department_id as "부서ID", department_name as "부서이름"
from departments
join employees using(department_id)
where department_id in(30, 90)
order by 1;

------------------------------------------------------------------------------------
--[문제4] 위치ID를 연결해서 사원이름,도시,부서이름을 출력하시오  ==> 52레코드
--        (관련테이블 : employees, locations2, departments)

--	조건1 : 사원이름 ,도시,부서이름로 제목을 표시하시오	
--	조건2 : Seattle 또는 Oxford 에서 근무하는 사원
--	조건3 : 도시순으로 오름차순정렬하시오 
--	조건4 : 모든 사원을 포함한다

--  사원이름      도    시     부서이름
-- ----------------------------------
--   Hall        Oxford       Sales

--[분석]
--employees                departments            locations2
-- -----------------------------------------------------------
--department_id            department_id
--                         location_id              loc_id            
select last_name as "사원이름", city as "도시" , department_name as "부서이름"
from employees
left join departments using(department_id)
left join locations2 on(location_id=loc_id)
where city in('Seattle', 'Oxford')
order by city asc;
------------------------------------------------------------------------------------
--[문제5] 부서ID,나라ID,부서위치를 연결해서 다음과 같이 완성하시오   -- 1 레코드
--        (관련테이블 : employees,locations2, departments,countries)
--      조건1 : 사원번호,사원이름,부서이름,도시,도시주소(street_address),나라명로 제목을 표시하시오
--      조건2 : 도시주소에  Vi 또는 St가 포함되어 있는 데이터만 표시하시오
--      조건3 : 나라명, 도시별로 오름차순정렬하시오
--      조건4 : 모든사원을 포함한다
select employee_id "사원번호", last_name "사원이름", 
         department_name "부서이름", city "도시", street_address "도시주소", 
         country_name "도시주소", country_name as "나라이름"
from employees
left join departments using(department_id)
left join locations2 on ( location_id = loc_id)
left join countries using (country_id)
where street_address like '%Vi%' or street_address like '%St%'
order by 6, 4;