본문 바로가기

배우기/복습노트[oracle sql]

[복습] SQL | Oracle 첫 번째 마주한 큰 산, join (3) - join 복습

728x90
반응형

어제 join 공부한 내용을 토대로 정리를 해보자면,

 

1. join 조건 형태에 따라

  1) equi join

    ansi 표준) from table1 join table2

  2) non equi join

    ansi 표준) from table1 join table2

 

 

2. 출력 데이터 생략 여부에 따라

  1) inner join(기본)

    ansi 표준) from table1 join table2

  2) outer join

    ansi 표준) from table1 left/right outer join table2

 

3. join 형태에 따라

  1) cross join: 카티시안 곱이 출력되는 형태

    oracle 표준)

      select * 

         from emp, dept;    (그냥 나열하면 된다, join 조건 명시하지 않으면 cross join이 발생함.)

    ansi 표준)

      select *

        from emp cross join dept;  (cross join 생략하면 natural  join이 된다, join 조건 생략 시 자동으로 양 테이블에 같은 이름의 컬럼으로 join)

  2) natural join

    oracle 표준)

      select * 

        from emp natural join dept;

oracle DBMS에서 natural join을 발생시키려면 위와 같이 쓰면 된다. 그럼 oracle DBMS에서 ansi 표준을 쓰면 어떻게 될까? ansi 표준에서는 natural join을 생략하면 된다. 그러나 oracle DBMS에서 natural join을 생략하게되면 oracle 표준으로 인하여 cross join이 발생하게 된다. 그래서 사실상 방법이 없다. ansi 표준도 저렇게 써야 할 것이다.

즉, ansi 표준은 이론적으로 join 조건을 생략하면 natural join이지만 oracle DBMS에서 실제 문법을  구현하는 과정에서 join 컬럼을 생략하게 되면 cross join이 발생하게 된다. 그러다보니 natural join을 발생시키려면 저렇게  natural join 을 써야한다.

natural join은 가급적 안 쓰는 게 좋은 게, deptno가 같으면서 name이 같을 수가 없기 때문이다. 

아래 예시로 설명을 하겠다.

          emp                                     dept
name   deptno   sal               name    deptno
   A         10       800               인사부    10
   B         20     1800               재무부     20

 

테이블 레이아웃이 위와 같을 때, natural join을 하게 되면 emp.deptno = dept.deptno가 자동으로 걸리게 된다. 그런데 emp.name = dept.name도 같이 자동으로 걸리게 된다.

 

emp.deptno = deptno.deptno
and emp.name = dept.name    조건으로 join을 수행하게 되므로 데이터 출력이 되지 않는다.

 

 R과 파이썬은 natural join이 디폴트여서 join 조건 명시 안하면 모두 join을 하게 된다.

언어마다 기본 join 방식이 조금씩 다르다고하니 주의해야겠다.

 

natural join 설명이 길어졌다.

  3) self join

    ansi 표준)

      select *

        from table1 join table2

 

여기까지 정리 끝!

 

반응형

 

오늘은 복잡한 형태의 join을 배웠다.

 

case 1) 연이은 테이블 join 시의 outer join

s - p(+) - d(+)

학생의 소속학과를 출력하려는데 지도교수가 없는데 지도교수의 소속학과는 올 수가 없으므로 d에도 (+)를 해야한다.

예제를 하나 풀어보자.

 

각 학생의 이름, 학년, 지도교수명, 지도교수의 소속학과명을 출력하여라. 단, 지도교수가 없는 학생정보도 출력하여라.

이렇게 (+) 관계를 이해하여야 한다.

 

 

 

case 2) 테이블 연결구조가 순환 구조일 경우의 outer join

바로 예제로 적용하여 이해해보자.

student, exam_01 테이블을 사용하여 각 학생의 이름, 학년, 성적, 각 학생보다 같은 학년 내 시험성적이 높은 친구 수를 구하여라.

이 데이터를 풀기 위하여 몇 개의 join을 사용해야 할지를 고민해보며 접근하자.

일단 코드는 위와 같다.

 

단계별로 접근해보면,

일단 저렇게 다 출력해보자.

나보다 높은 친구가 몇 명인지 출력이 된다.

저 수를 카운트하면 되는 것이다.

전체 학생은 20명인데, 위의 출력된 결과를 보면 16명이 출력되었다.

이는 학년별로 제일 성적이 좋은 사람은 생략되었기 때문이다.

 

원래라면 아래와 같은 코드인데 에러가 난다.

순환구조로 (+)가 연결되어있기 때문이다.

outer join 완성하다보면 결국 s1까지 outer join을 수행하여, full outer join 구문과 같아져 에러가 발생하는 것이다.

그러나 순환구조 찾아가는 법을 위처럼 연습해보자. 테이블 연결 순서대로(s1 -> s2 ->  e2 -> e1 -> s1)

위 코드는 student s1, exam_01 e1이거를 하나의 테이블처럼,  student s2, exam_01 e2이거를 하나의 테이블처럼 처리한 것이다.

 

그러나 서브쿼리를 배우면 그 순환 구조를 깨트릴 수 있다.

서브쿼리는 집에 돌아가서 복습해야지. 학원 문 닫겠다.

728x90
반응형