Tip & Tech

SQL Server 2008 부터 사용가능


Union 이나 union all 이 데이터의 합집합을 구하는것이라면


- intersect 는 두개의 테이블에 데이터가 동시에 존재하는 교집합을 구하는 것이고

- except 는 첫번째 테이블에는 있고 두번째 테이블에는 없는 데이터만을 구하는 차 집합을 구하는것이다.


이에반해 join 은 데이터의 수평적 결합이고 union 은 두개의 테이블에 데이터 존재여부를 검사하지 않고 무조건 합치는 데이터의 합집합이다.


기존에 교집합이나 차집합을 구하기 위해 복잡한 쿼리를 작성해야 했다면 이 두 연산자를 통해 기존 join 이나 group by 를 통해 구현했어야 할 복잡한 쿼리를 매우 간단하게 처리할 수 있게 되었다.
Intersect 를 통해 구현할 수 있는 쿼리의 편안함을 예로 들어보자

 
select * into Company1
from (
values ('Bohler Uddeholm Spec Metals','South Boston','VA')
,('Cigital Inc','Sterling','VA')
,('Texas Citrus Exchange','Mission','TX')
,('Garden State Tanning Byron WD','Williamsport','MD')
,('Byram Realty','Lexington','GA')
,('Blue Moon Graphics','Charleston','SC')
,('Lake Tahoe Community College','South Lake Tahoe','CA')
,('Pyramind','San Francisco','CA')
,('Twisp Chamber Of Commerce','Twisp','WA')
,('Dalsin Industries','Bloomington','MN')) Tab (comname, city, state)

select * into Company2
from (
values ('Bohler Uddeholm Spec Metals','South Boston','VA')
,('Cigital Inc','Sterling','VA')
,('Texas Citrus Exchange','Mission','TX')
,('Blue Moon Graphics','Charleston','SC')
,('Lake Tahoe Community College','South Lake Tahoe','CA')
,('Pyramind','San Francisco','CA')
,('Twisp Chamber Of Commerce','Twisp','WA')
,('Dalsin Industries','Bloomington','MN')
,('A Beautiful Celebration','Leesburg','FL')
,('Bumper To Bumper','Valley','AL')
,('Alpha Graphics','Baton Rouge','LA')
,('ARH Air Cond Refrig & Heat','Wewahitchka','FL')
,('Bama Golf Carts','Sylacauga','AL')
,('Baggett Consulting','Fairhope','AL')
,('Byrd''s Western Store','Melbourne','FL')
,('Byrd Tile Distributors','Raleigh','NC')
,('Ronald Mc Donald House','Columbus','OH')) Tab (comname, city, state)



두개의 테이블( company1 과 company2) 에 동시에 존재하는 회사를 뽑기위한 쿼리이다


select comname, city, state, lastname from company1
Intersect
select comname, city, state, lastname from company2

결과는 아래와 같이 두개의 테이블에 조인해서 뽑은 결과와 같이 나온다


위와 같이 단순이 두 쿼리를 intersect 연산자를 이용하여 붙여주면 양쪽 테이블에 모두 존재하는 데이터만 distinct 한 상태로 추출해 준다. 

이것을 intersect 없이 구현하려면 아래와 같이 복잡한 조인 쿼리나 union group by 쿼리를 사용하여 처리해야 한다. 

select distinct a.comname, a.city, a.state
from company1 a inner join company2 b 
	on a.comname = b.comname
	and a.city = b.city
	and a.state = b.state

또는 

select comname, city, state
from (
select distinct comname, city, state from company1
union all
select distinct comname, city, state from company2
) A
group by comname, city, state
having count(*)=2
 

이렇게 두개의 테이블 일때는 그래도 할만하지만 비교해야할 테이블이 4~5 개 이상으로 늘어나면 쿼리가 한페이지가 넘어가고 에러가 날경우 뭐가 잘못된건지 찾는것도 쉽지 않다.


다음으로 except 는 차집합을 구하는 마이너스 쿼리이다. 위 테이블에는 있고 아래 테이블에는 없는 데이터를 추출한다.


위에서 사용한 company1, company2 테스트 테이블로 쿼리를 실행해 보면 company1 에는 있고 company2 에는 없는 데이터를 추출한다.


 
select comname, city, state from company1
except
select comname, city, state from company2
 


위의 except 쿼리를 기존 연산자로 쿼리하려면 not exists subquery 를 이용해야 하는데 중복 체크해야 하는데 칼럼이 많을경우 쿼리가 매우 복잡해지고 명확하지 않다.

select comname, city, state from company1 a
where not exists(
	select 1 from company2 
	where comname=a.comname and city=a.city and state=a.state
)


위 두개의 쿼리 모두 아래와 같이 두건의 데이터를 동일하게 리턴해준다.




위와 같이 intersect 나 except 가 위아래 동일한 칼럼을 추출할때는 매우 유용한 연산자이지만 추출해야 할 칼럼이 다르거나 특정칼럼을 조건으로 존재여부를 체크해야 할경우는 여전히 기존 조인이나 exists 구문을 사용하는 것이 유용한 경우가 훨씬 많다.


따라서 이런 연산자가 있다는 것을 알아두고 필요할경우 사용하면 쿼리문이 단순해 질수 있지만 기존에 사용했던 조인이나 exists 쿼리의 쓰임새를 확실히 알아 두어야 막힘 없이 쿼리를 사용할수 있게 된다.


실제 현업에서 쿼리의 구문을 정확히 알필요는 없다. 자주 사용하는 쿼리의 구문만 알고 있으면 되고, 특정 케이스에 특정 연산자를 사용하면 효율적이다는 것만 알고 있으면 필요할때 구문은 찾아서 작성하면 된다.


DBA 업무를 하다보면 이렇게 두루두루 사용 가능한 기능들을 인지하고 있는것이 도움이 되는경우가 많이 있다.