Programming/SQL

UNION, VIEW. 2021-08-13

최동훈1 2021. 8. 13. 17:10

우선 union 이라는 개념은 집합 개념이라고 생각하면 쉽다. 일단 union의 종류에는 총 4가지가 있다. 바로 union, union all, intersect, minus 드이 있다. 차례대로, 합집합, 중복을 허용하는 합집합, 교집합, 차집합 으로 설명 가능하다. 또한 집합연산의 대상이 되는 테이블은union 연산자 기준 앞에서 선별된 테이블 들이다.

 

select * from member 
union
select * from student;

이렇게 쿼리를 작성하면, member 테이블의 레코드들과 student 테이블의 레코드 들이 '공통된 부분'을 제외하고 합쳐진다.

그런데 조건이 있다. 각 합쳐지는 레코드들의 칼럼 수가 서로 같아야 한다. 왜냐하면, join 키워드는 테이블 두개를 통채로 서로 합치는 것이라, 칼럼의 수는 달라도 되지만, union은 레코드 들의 기계적 결합이기 때문에 칼럼의 수가 같아야 한다.

칼럼의 값은 다르지만 같은 NVARCHAR2 데이터형을 칼럼값으로 가지는 칼럼으로 테스트를 해보자.

select ID,name from member
union
select PWD,name from member;

ID 자리에 PWD 의 값이 기계적으로 결합되었다.  이렇게 union은 조건이 다른 같은 테이블을 대상으로도 칼럼의 수만 같다면, 시행할 수 있다.

그런데 만얄 연산을 하는 테이블의 칼럼 수가 서로 다르다면?

select ID,name,pwd from member
union
select PWD,name from member;

그 전과 달리 pwd라는 칼럼이 하나 더 추가된 테이블과 union 결합을 할려니

오류메세지

이런 결과를 초래한다. 

그렇다면 서로 다른 테이블 간의 결합은 어떨까?

select title,content from notice 
union
select name,id from member;

이렇게 나온다. ! 서로 결합시키고자 하는 레코드들의 칼럼별 데이터 형이 같지 않다면, 결합을 못하는 거 같다.

왜냐하면 union 자체가 어떤 한 레코드의 칼럼을 기준으로 정렬되는 것이기 때문이다. 그렇다면 서로서로 타입이 맞는 칼럼들에 대한 union 연산을 해 보자.

칼럼별 데이터형이 union 하려는 레코드의 칼럼별 데이터형과 일치해야함.

notice의 칼럼인 id, title는 모두 NVARCHAR2 형이고, member 에서도 id, name 은 NVARCHAR2 형 이므로 이 두 칼럼으로 각 테이블을 union 해 보자.

select id,title from notice
union
select id,name from member;

이렇게 나온다. 이것은 union all 이아닌 일반 union 이기 떄문에 중복된 것은 나오지 않는다.

minus, intersect 연산자 모두 위와 같은 원리인데 단지 union과 차이점은  각 레코드들의 차집합, 교집합 이다.

 

**

1. union 연산자는 서로다른 두 레코드들의 기계적인 결합이다.

2. union 연산들을 하기 위해선 각 레코드들의 칼럼의 개수, 칼럼속 데이터 타입 등이 같아야 한다.

 

저번에 내가 쓴 관계형 데이터 베이스에 대한 포스팅 에서는 일단 데이터의 무결성 때문에, 중복되는 데이터를 줄이고, 테이블을 분리해서 저장한다고 했다.( 지난 포스팅 참고). 그런데 문제가 있다. 우리가 직접적으로 사용하는 테이블은 각기 테이블끼리 관계를 맺은 전체 테이블을 놓고 사용할 것인데, 그렇다면 이럴떄마다. join으로 하나하나 테이블을 다시 연결시켜야 해야한다. 그래서, 이런 불필요한 과정을 막고, 테이블을 저장하는 방식과 사용할때 쓰는 테이블을 나누어서 무결성과 간소화. 이 두마리 토끼를 모두 잡는 개념이 뷰(view) 이다. 

뷰라는 이름 그대로 이것은 각각 분리되어 저장되있는 테이블을 어떤 연결적 측면에서 보여지는지를 마치 테이블인것 처럼 사용할수 있도록 만든 구조이다.

 

직접 사례를 보여주겠다. 일단 member 테이블의 인적사항과 해당 사람이 쓴 글 내용을 "보고"(VIEW) 싶다면 이런 쿼리를 쓰면 된다.

create view "member+notice"
as
select m.name,n.content from member m left outer join notice n on m.name=n.writer_id;

보고 라는 단어를 강조한 이유는, view 를 만든 이유가 이미 다 내포되어 있기 때문이다. 이렇게 분리되어서 저장된 테이블들을 join 키워드 없이 한번에 보고 싶다면 이렇게 뷰를 만들면 된다.

또한 이 뷰는 테이블은 아니지만, 실제로 테이블과 같이 동작하게 할 수 있다. 예를 들면, 집계함수나 문자열 검색 등을 말이다. 그냥 이름만 뷰이고, 새롭게 만들어낸 테이블이라 생각해도 무방하다.

이렇게 별도로 마련된 공간에 create를 통해 만들어낸 뷰가 있다.

 

공부시간 2시간.

순공시간 1시간.

 

오늘은 오후에 또 병원으로 외근가서 오후 공부를 다 못했다. 그래서 헬스장 갔다가 집에 와서 못다한 공부를 다했다. 순간적으로 내일 주말인데 미뤗다고 내일 하면 되지 않을까? 이런 생각이 잠깐 들었지만, 한번 밀리면 끝이라는 어느 한 수능 인강 강사의 말이 떠오르고 하기싫은 마음을 붙잡고 끝까지 오늘 공부한 내용을 내 머릿속으로 채워넣었다. 내일은 울산에 비온다는데, 점심먹고 헬스장 갔다가 머리 자르러 가야겠다.