#title Between Join을 Hash Join으로 between join을 하면 loop join이 된다. hash join으로 바꿀 수 없냐고 동료가 물어봐서 정리해보았다. 다음과 같이 테이블이 있다. {{{ drop table #temp_seg create table #temp_seg ( seg_nm varchar(50), bdt date, edt date ) insert into #temp_seg values ( '01_8월일~16일', '2012-08-01', '2012-08-16') insert into #temp_seg values ( '02_8월일~15일', '2012-08-03', '2012-08-15') insert into #temp_seg values ( '03_7월일~31일', '2012-07-01', '2012-07-31') ;with dummy as ( select convert(datetime, '20120701') dt union all select dt + 1 from dummy where dt + 1 < '20120816' ) select dt into #dt from dummy option (maxrecursion 0); }}} 다음과 같이 하면 hash join이 안된다. loop join 밖에 안 된다. 왜냐하면 '=' 연산자가 없기 때문이다. {{{ select * from #temp_seg a inner hash join #dt b on b.dt between a.bdt and a.edt /* 메시지 8622, 수준 16, 상태 1, 줄 1 이 쿼리에 정의된 힌트로 인해 쿼리 프로세서에서 쿼리 계획을 생성할 수 없습니다. 힌트를 지정하거나 SET FORCEPLAN을 사용하지 않고 쿼리를 다시 전송하십시오. */ }}} hash join은 반드시 '=' join을 해야 하므로 강제로 '='을 만들어 준다. 상수를 이용하면 옵티마이저가 상수인 것을 알기 때문에 안 된다. 다음과 같이 옵티마이저를 속인다. {{{ select * from #temp_seg a inner hash join #dt b on b.dt between a.bdt and a.edt and datalength(checksum(a.bdt)) = datalength(checksum(b.dt)) }}} 이렇게 hash join 된다. checksum() 함수는 매개변수로 숫자형이든 문자형이든 다 받아들이며, 해시함수로 int형의 값을 리턴한다. datalength()함수는 매개변수의 데이터 크기(byte)를 리턴한다. 그러므로 위의 sql에서 보면 int형의 byte수인4가 함수의 리턴값이다. 즉, datalength(checksum(a.bdt)) = datalength(checksum(b.dt)) = 4.