#title 셀프조인 업데이트 [[TableOfContents]] ==== 문제의 SQL문장 ==== 예제에서는 #temp가 몇 건 되지 않지만, 실제로는 4천 만 건 가량이었다. {{{ --drop table #temp create table #temp( a varchar(20) , i int , ranking int ) insert #temp(a, i) values('a', 1) insert #temp(a, i) values('a', 2) insert #temp(a, i) values('a', 3) insert #temp(a, i) values('b', 10) insert #temp(a, i) values('c', 5) insert #temp(a, i) values('b', 7) insert #temp(a, i) values('e', 8) select * from #temp order by 1,2 /* a i ranking -------------------- ----------- ----------- a 1 NULL a 2 NULL a 3 NULL b 7 NULL b 10 NULL c 5 NULL e 8 NULL */ update a set a.ranking = b.ranking from #temp a inner join ( select a , i , rank() over(partition by a order by i) ranking from #temp) b on a.a = b.a and a.i = b.i select * from #temp order by 1,2 /* a i ranking -------------------- ----------- ----------- a 1 1 a 2 2 a 3 3 b 7 1 b 10 2 c 5 1 e 8 1 */ }}} 이 SQL은 셀프 조인으로 [Merge Join]으로 풀리면서 4천 만 건에 대한 1회의 정렬도 포함되었다. 또한 2번의 풀스캔을 한다. 필자는 다음과 같은 방식으로 1회의 풀스캔으로 풀리게 하였다. ==== 해결 방안 ==== {{{ update a set ranking = up_ranking from ( select a , i , ranking , rank() over(partition by a order by i) up_ranking from #temp) a }}} 필자는 알고 있던 것이 아니고, 고민을 하다가 View 연산의 일종이므로 되리라 생각하고 밑져야 본전의 심정으로 해봤다. 그런데 실행이 잘 되는 것이 아닌가? 허허..