SQL Join 에 대해서
테이블에서 가로는 Row를 의미한다.
Row 와 Row를 연결하려면 공통요소가 있다면 쉽게 연결할수 있을것이다.
물론 아무의미가 없더라도 모든 가능한 경우 값을 보기 위해서 무작위로도 연결할수는 있다.
테이블에서 세로는 컬럼을 의미하며,
컬럼은 공통된 데이터 형식이 있으므로 이 제약을 어기면 연결될수 없다.
따라서 세로로 연결할때에는 반드시 공통된 데이터 형식이어야만 연결이 가능하다.
가로로 연결하는 방식이 바로 join 이고,
세로로 연결하는 방식이 바로 Union 방식이다.
INNER JOIN
이는 두집합 간에 공통으로 존재하는 요소들을 추출하기 위한 연산이다.
RDBMS에서 이개념은 INNER JOIN QUERY 로 표현된다.
create table SET_A(ID INT) go create table SET_B(ID INT) go begin insert SET_A values(1) insert SET_A values(2) insert SET_A values(3) insert SET_b values(2) insert SET_b values(3) insert SET_b values(4) end
대상이 되는 두 집합을 Inner join 구문으로 연결하고 ON 이하에서 공통으로 존재할 요소를 지정한다. 이렇게 공통으로 존재할 요소를 JOIN KEY라고 한다.
select * from set_a as a inner join set_b as b on a.id = b.id
일반적으로 JOIN KEY는 두 테이블간의 관계를 표현하며, 이는 참조되는 키, 참조키 관계, 외부 키 제약조건등으로 표현되기도 한다.
하지만 쿼리 사용하는 사람의 의도에 따라 PARENT-CHILD KEY 가 아니더라도 JOIN KEY가 선택될수도 있다.
OUTER JOIN
OUTER JOIN은 차집합이 아니다.
차집합은 A-B 이다. A-B는 A 집합에서 B 집합에 있는 요소들을 모두 뺀 나머지 이고,
이는 A – (A ∩ B)라고 표현할수 있다.
오라클 같은경우에는 MINUS 연산으로, SQL서버나 다른 MINUS연산을 제공하지 않는 RDBMS의 경우에는 NOT EXIST 나 NOT IN 으로 표현된다.
OUTER JOIN 에는 LEFT, RIGHT, FULL OUTER JOIN 등 3가지 형식이 있다.
좌측 테이블의 요소를 결과에 포함시키라면 left 이고, 우측 테이블의 요소를 결과에 포함시키라면 right 이며, 양쪽다 포함할경우 FULL 이다.
select a.id, b.id from set_a as a left outer join set_b as b on a.id = b.id
ANSI 스타일의 OUTER JOIN의 T-SQL 버전에서 LEFT 는 *= 이며, RIGHT 는 =* 이다.
하지만 FULL *=* 이 아니다!
left 의 경우
select * from set_a a, set_b b where a.id *= b.id
right 의 경우
select * from set_a as a, set_b as b where a.id =* b.id
full 의 경우
select * from set_a as a full outer join set_b as b on a.id = b.id
sqlserver 2008 버전쓰는데 위의 코드에서 Ansi 가 아닌 어쩌고 저쩌고 해서 설정 바꾸라는 에러뜨면
ALTER DATABASE 데이터베이스명 SET COMPATIBILITY_LEVEL = 80 을 써주면 해결된다.
SELF JOIN
SELF JOIN 은 나 자신을 참조하는것이 아니라 동일한 테이블에서 여러번의 로우세트를 뽑아내 이를 대상으로 최종 결과 집합을 도출하는것이다.
select a.EmployeeID, a.LastName, a.FirstName, b.EmployeeID, b.LastName, b.FirstName from Northwind..Employees as a, ( select EmployeeID, LastName, FirstName from Northwind..Employees where EmployeeID = 2 ) as b where a.ReportsTo *= b.EmployeeID
차 집합
두집합 간의 차집합이라는 것은 하나의 집합에서 다른 집합을 뺀 나머지를 말하는것이다.
ASNI-SQL에서는 이런 차집합을 관계형 데이터베이스에서 구현하기 위해 EXECEPT 키워드를 정의햇다.
오라클에서는 MINUS라는 연산으로 A집합에서 B집합의 공통요소를 제거하는 역할을 수행한다.
첫번째는 A-B는 A집합에서 B집합의 원소를 제거하는것이다.
create table 집합A (c1 int) create table 집합B (c1 int) insert 집합A values(1) insert 집합A values(2) insert 집합A values(3) insert 집합A values(4) insert 집합A values(5) insert 집합B values(4) insert 집합B values(5) insert 집합B values(6)
NOT EXISTS 구문은 첫번째 집합과 두번째 집합의 교집합을 제거하는데 사용되었다.
즉, 전체A-(A∩B)이다. A∩B로 차집합을 하는 이유는
이것이 B의 전체 집합보다 작으면서 효율적으로 작동하기 때문이다.
쿼리 성능을 개선하는데 가장좋은 방법은 처리할 데이터의 크기를 최소한으로 줄여주는것이다.
그런 이유로 NOT IN 보다는 NOT EXISTS 구문이 훨씬 효율적이다.
NOT EXISTS는 서브쿼리가 True인지 False 인지 체크한다
select A.* from 집합A as A where NOT EXISTS (select * from 집합B where c1 = A.c1)
결과는
c1 값 1, 2, 3
이 나온다.
두번째 방법은 A∩Bc을 사용하는것이다.
교집합은 조인을 의미한다. Bc라는건 B의 여집합을 의미한다.
즉 B의 요소들이 아닌것이고, B테이블에는 존재하지 않는 값들과 조인한다는 의미이다.
결론적으로 교집합을 하는데 B의 요소들은 배제하라는 의미다.
T-SQL로 하자면
LEFT OUTER JOIN + B IS NULL 이 된다.
LEFT OUTER JOIN이 되는이유는 A집합을 기준으로 B를 연산하는데에 A의 모든 요소를 사용해야 하기 때문이다.
B-A라면 당연 RIGHT OUTER JOIN 이다. B IS NULL이 되는 이유는 A 요소에 매칭되는 B의 요소들이 없다는 것이며,
그러한 B의 요소들이 A집합에 속하지 않는 여집합의 요소임을 의미한다.
select from where 집합A as A left outer join 집합B as B on A.c1 = B.c1 where B.c1 is null
결과는 역시
c1 값 1, 2, 3
이 나온다.
교집합
교집합은 INNER JOIN쿼리다. 집합A와 집합B의 공통집합을 나타내는 것이 교집합이다.
차집합에서 마찬가지로 INNER JOIN 쿼리를 사용하지 않는 경우에는 EXISTS쿼리로 유도하여 사용할수 있다.
하지만 INNER JOIN자체가 SARG이기에 굳이 EXISTS를 사용할 필요는없다.
EXISTS의 활용
select A.* from 집합A as A where EXISTS (select * from 집합B where c1 = A.c1)
inner join의 활용
select A.* from 집합A as A inner join 집합B as B on A.c1 = B.c1
둘의 결과 C1 의 값 4, 5 가 나온다.
합집합
A∪B 또는 A+B 로 나타내며, 한 원소가 두 집합중 하나에 속한다는것을 의미한다.
즉, 한 원소가 두 집합 모두(집합의 교집합)에 속할수 있음을 의미한다.
합집합연산은 두 집합의 원소를 모으는것으로 연산된다.
T-SQL에서 합집합은 두가지 방식으로 처리될수 있다.
UNION과 UNION ALL의 두가지 방식이다.
차이는 두개의 집합을 하나의 집합으로 모을때,
두 집합의 공통요소(교집합의 원소)를 다 표현하느냐,
아니면 중복값을 제외하여 결과 처리할것인가의 기준이다.
즉, 두 집합 A= {1, 2, 3, 4, 5}, B= {4, 5, 6}의 예에서
A UNION B 는 {1, 2, 3, 4, 5, 6} 이며,
A UNION ALL B 는 {1, 2, 3, 4, 5, 4, 5, 6} 이다.
select * from 집합A union all select * from 집합B select * from 집합A union select * from 집합B
UNION ALL 은 대상집합들의 모든 원소를 모아 놓은것이되며,
UNION은 결과 집합을 DISTINCT 한것이 된다.
참고
상기의 내용은 손호성님의 “SQL Server 2005 완벽가이드 책”을 보며 필기한 내용입니다.
No Comments