서버 개발/프로그래머를 위한 RDBMS

SQL 집합의 가공

지노윈 2020. 5. 27. 10:46
반응형
  • 합집합 : UNION
  • 차집합 : EXCEPT
  • 교집합 : INTERSECT
  • 집합간의 곱(cartesian product) : Join
  • 정의역 : WHERE 조건으로 변경
    and : 정의역 범위 줄어듬
    or : 정의역 범위 늘어남
  • 치역 : SELECT 항목, group by로 변경

 

Join

관련된 다른 집합을 찾아 오는 것이 아닙니다.

Join은 집합간의 곱으로 생각하세요.

"1쪽과 M쪽을 조인한다"는 "1 * M만큼의 데이터가 M쪽을 기준으로해서 1쪽에 복제되서 만들어진다."로 생각해야 합니다.

 

세로 데이터를 가로로 바꿀때 : sum(case when ...) 

가로를 세로로 바꿀때 : 1 x n 을 Join 하여 n건으로 복제해서 얻음

데이터를 복제 : copy_t를 이용하여 묻지마 조인하여 복제

 

- 카피 테이블
다음과 같이 실행하여 미래 copy_t를 만들어 두고 사용하면 편리합니다.

create table copy_t ( seq int, seq_var varchar(2) )

with temp as ( 
	select 1 as seq 
	union all 
	select seq + 1 from temp where seq < 99 ) 
insert into copy_t ( seq, seq_var ) 
	select seq, replicate('0',2-len(cast(seq as varchar))) + cast(seq as varchar) 
	from temp option(maxrecursion 0)

다음과 같이 01~99 까지 데이터가 생성됩니다.

 

 

 

 

 

 

 

 

 

 

 

- 집합적 사고 예 : 합계 출력

create table xxx (
name NVARCHAR(30) NOT NULL,
value INT NOT NULL
);
GO

insert into xxx values 
('A', '90'),
('B', '80'),
('C', '100')

copy_t를 사용하여 3건의 데이터를 2번 복사 합니다.

select * from xxx, (SELECT seq FROM copy_t where seq <= 2) b

seq가 2인 것의 name을 계로 만듭니다.

select case when seq = 1 then name else '계' end name, value
from xxx, (SELECT seq FROM copy_t where seq <= 2) b

name으로 group by하여 최종적으로 원하는 결과를 얻습니다.

select name, sum(value) val from (
	select case when seq = 1 then name else '계' end name, value
	from xxx, (select seq from copy_t where seq <= 2) b) aa
group by name

- 집합적 사고 예2 : 방사형 모델 조회

다음과 같이 생긴 모델링을 방사형 모델이라고 하며 친구 유저(friend)와 차단 유저(blocking)를 한 번에 조회하여 각각 몇명이 있는지 조회해 봅시다. 

스키마와 테스트 데이터를 다음과 같이 만들어 줍니다.

-- 친구 유저
drop table friend
create table friend (
userno BIGINT NOT NULL,
friend_userno BIGINT NOT NULL
);
insert into friend values
	(1, 11),
	(1, 12),
	(1, 13),
	(2, 22),
	(2, 23)

-- 차단 유저
create table blocking (
userno BIGINT NOT NULL,
blocking_userno BIGINT NOT NULL
);
insert into blocking values
	(1, 20),
	(1, 21),
	(1, 22),
	(3, 1),
	(3, 2)

UNION으로 집합을 합칩니다.

SELECT userno, friend_userno, null blocking_userno
FROM  friend
UNION ALL
SELECT userno, null friend_userno, blocking_userno
FROM  blocking

여기서 UNION과 UNION ALL의 어떻게 다른지 아시는 분?

UNION은 동일한 데이가 있으면 하나로 합쳐줍니다. CONCAT/MERGE UNION은 결과가 정렬되며, HASH UNION은 그렇지 않습니다.

어쨌든 합쳐주기 위한 추가 연산이 있으므로 UNION ALL 보다 무겁습니다. UNION ALL은 단순히 합치기만 하므로 빠릅니다.

 

UNION한 데이터를 GROUP BY합니다.

SELECT userno, count(friend_userno) friend_count, count(blocking_userno) blocking_count
FROM (SELECT userno, friend_userno, null blocking_userno
      FROM  friend
      UNION ALL
      SELECT userno, null friend_userno, blocking_userno
      FROM  blocking) a
GROUP BY userno

 

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - 게임 서버 프로그래머가 알아야 할 RDBMS

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - 옵티마이저 맛보기

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - 테이블 조인 하면 느리다?

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - 리커시브 모델의 활용

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - 아크 모델(exclusive or)에서의 주의점

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - 부분범위 처리와 전체 범위처리

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - 인덱스의 제대 사용하자

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - DB 옵티마이저

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - Nested Loop/Sort Merge/Hash Join

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - DB 테이블 클러스터링 팩터

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - DB 절차적 사고 VS 집합적 사고

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - SQL 집합의 가공

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - SQL IN의 특징과 IN의 활용

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - 서브 쿼리 활용

[데이터베이스/게임 서버 프로그래머가 알아야 할 RDBMS] - 인라인 뷰의 활용