2021.01.28

테이블 별칭 정리

--employee테이블의 job_code와 job테이블의 job_code가 연결되어 있음
select * from employee;
select * from job;

--별칭을 뺀다면 테이블명을 그대로 적어줌     
--why? 따로 부를 이름이 없기 때문
select *
from employee join job
    on employee.job_code = job.job_code;

--Error : "column ambiguously defined" 컬럼이 모호하게 정의되어있다.
--어디에 있는 job_code인지 모르기 때문
select emp_name, job_code, job_name
from employee join job
    on employee.job_code = job.job_code;

--테이블명을 반드시 명시해줘야함
(emp_name은 employee에만 존재, job_name은 job에만 존재하는 컬럼인걸 알지만, 
job_code는 두 테이블 모두에 존재하기때문 - 이 때 job의 job_code를 가져오든, 
employee의 job_code를 가져오든 상관없다. 값이 같기때문)
select emp_name, job.job_code, job_name
from employee join job
    on employee.job_code = job.job_code;

--but 테이블명을 일일이 써주기란 번거로움 -> 별칭 사용
(대소문자 구분하지 않음, 알파벳이 아닌 EMPL, JB 이런식으로 써도 됨)
select E.emp_name, J.job_code, J.job_name
from employee E join job J
    on E.job_code = J.job_code; 

--기준컬럼명이 좌우테이블에서 동일하다면, on 대신 using 사용가능
(on과 달리, ()안에 사용할 기준컬럼명을 담아주면된다.)
select *
from employee join job
    on employee.job_code = job.job_code; --on Ver. 16열

select *
from employee E join job J
    using(job_code); --using Ver. 15열
--출력 : using에 사용하는 컬럼이 맨 앞컬럼으로 빼내면서, 중복된 것을 한번만 출력해줌
    
--using을 사용한 경우는 E.jobcode, J.jobcode와 같은 해당컬럼에 별칭을 사용할 수 없다
--why? 공통된 것을 하나로 합쳐서 한번만 출력하기 때문
--ORA-25154: column part of USING clause cannot have qualifier
select E.emp_name,
             job_code, --별칭 사용불가
             J.job_name
from employee E join job J
    using(job_code);

equi-join 종류

  1. inner join 교집합 (두 테이블의 공통된 부분만 추려냄)

  2. outer join 합집합

    • left outer join 좌측테이블 기준 합집합
    • right outer join 우측테이블 기준 합집합
    • full outer join 양테이블 기준 합집합
  3. cross join
    두테이블간의 조인할 수 있는 최대 경우의 수를 표현
    (행과 행이 만날 수 있는 모든 경우를 보여줌)

  4. self join
    같은 테이블의 조인

  5. multiple join
    3개 이상의 테이블을 조인

    inner & outer join을 교집합, 합집합과같은 집합개념으로 표현한 사진

    inner & outer join은 위 사진과같이 이해하면 좋다.

    ↑INNER JOIN(ANSI 표준문법.Ver)

    ↑INNER JOIN(ORACLE 전용문법.Ver)



    ↑OUTER JOIN(ANSI 표준문법.Ver)

    ↑LEFT OUTER JOIN(ORACLE 전용문법.Ver)

    ↑RIGHT OUTER JOIN(ORACLE 전용문법.Ver)

    ↑FULL OUTER JOIN은 ORACLE 전용문법 없음

    ↑INNER & OUTER JOIN 각자 사용하면 좋은 경우의 예시

@ 강의중 inner & outer join 예제문제: 학번/학생명/담당교수명 조회

--0.문제에서 원하는 조회값이 있는 테이블 찾기 -- tb_student, tb_professor
--1.두 테이블의 기준컬럼 찾기(join 시키기위해서)
--2.on조건절에 해당되지 않는 데이터파악

--1. join시키기 위해, 두 테이블에 모두 있는 값의 기준컬럼명 찾기
select * from tb_student; -- coach_professor_no
select * from tb_professor; -- professor_no

--2. on조건절에 해당하지 않는 데이터파악
--2-1. 교수배정을 받지 않은 학생 조회 -- 9(left)
select count(*)
from tb_student
where coach_professor_no is null;

--2-2. 담당학생이 한명도 없는 교수 조회 -- 1(right), P114 백혁호는 담당학생이 없다.
--전체 교수 수 -- 114
select count(*)
from tb_professor;
--중복 없는 담당교수 수 -- 113, 전체교수 수에서 이 값을 빼면 담당학생이 없는 교수의 수임
select count(distinct coach_professor_no)
from tb_student;


--담당교수, 담당학생이 배정되지 않은 학생 제외 : inner 579
select student_no, student_name, professor_name
from tb_student S join tb_professor P
    on S.coach_professor_no = P.professor_no;
    
select count(*)
from tb_student S join tb_professor P
    on S.coach_professor_no = P.professor_no; -- inner join시 원하는 검색조건에 맞게 데이터가 걸러져서 
    						 몇개의 행을 갖는지 알아보기위해 count했음

--담당교수가 배정되지 않은 학생 포함 : left 588 = 579(inner) + 9
select student_no, student_name, professor_name
from tb_student S left join tb_professor P
    on S.coach_professor_no = P.professor_no;

--담당학생이 없는 교수 포함 : right 580 = 579(inner) + 1     
select student_no, student_name, professor_name
from tb_student S right join tb_professor P
    on S.coach_professor_no = P.professor_no;


↑CROSS JOIN(ANSI 표준문법.Ver)

↑CROSS JOIN(ORACLE 전용문법.Ver)

↑SELF JOIN(ANSI 표준문법.Ver)

↑SELF JOIN(ORACLE 전용문법.Ver)



↑사원들의 사원명, 부서명, 지역명, 직급명 조회를 위해 테이블 MULTIPLE JOIN시 연결되는 순서
((employee + department) + location) + job

↑MULPIPLE JOIN(ANSI 표준문법.Ver)

↑MULPIPLE JOIN(ORACLE 전용문법.Ver)

↑MULPIPLE JOIN 최종끝판왕!(ANSI 표준문법.Ver)

↑MULPIPLE JOIN 최종끝판왕!(ORACLE 전용문법.Ver)

MULTIPLE JOIN까지 진도나간상태에서 풀어보는 실습문제

/*
2021.01.28 실습문제1(1~5)
*/
--@실습문제 1 : 학번, 학생명, 학과명 조회
-- 학과 지정이 안된 학생은 존재하지 않는다.
select S.student_no, S.student_name, D.department_name
from tb_student S
    inner join tb_department D
        on S.department_no = D.department_no; --588명
         
select count(*)
from tb_student
where department_no is null; --학과 지정이 안된 학생이 있는지 확인해보고싶을때, 
                               학과 지정이 안된 학생은 존재하지 않는다.

--@실습문제 2 : 수업번호, 수업명, 교수번호, 교수명 조회
select C.class_no, C.class_name, P.professor_no, P.professor_name
from tb_class_professor CP
    join tb_class C
        on CP.class_no = C.class_no
    join tb_professor P
        on P.professor_no = CP.professor_no; --776개

--@실습문제 3 : 송박선 학생의 모든 학기 과목별 점수를 조회(학기, 학번, 학생명, 수업명, 점수)
select G.term_no, 
student_no, S.student_name, C.class_name, G.point --S.student_no 사용불가,
                                                    using에 사용된 컬럼은 별칭으로 쓸수없다.
from tb_grade G
    join tb_student S
        using(student_no)
    join tb_class C
        using(class_no)
where S.student_name = '송박선';

--@실습문제 4 : 학생별 전체 평점(소수점이하 첫째자리 버림) 조회 (학번, 학생명, 평점)
--같은 학생이 여러학기에 걸쳐 같은 과목을 이수한 데이터 있으나, 전체 평점으로 계산함.
select student_no, student_name, trunc(avg(point), 1) avg
from tb_grade G
    join tb_student S
        using(student_no)
group by student_no, student_name; --588명

--@실습문제 5 : 교수번호, 교수명, 담당학생명수 조회
-- 단, 5명 이상을 담당하는 교수만 출력
select P.professor_no, P.professor_name, count(*) cnt
from tb_student S
    join tb_professor P
        on S.coach_professor_no = P.professor_no
group by P.professor_no, P.professor_name
having count(*) >= 5
order by cnt desc; --68명


cf) ctrl누르고 테이블명(예를들어 employee) 누르면 위사진처럼 자바에서처럼 편리하게 조회가능
테이블의 정보와 값을 select * from employee; 이렇게 코드를쳐서 직접 조회하지 않아도
열이나 데이터 탭을 클릭하면 join시에 어떤 컬럼을 가져다 쓸지 빠르게 확인가능
완전 편리함

좋은 웹페이지 즐겨찾기