#title 선수수익 [[TableOfContents]] ==== 선수수익이란? ==== 네이버 용어 사전에는 선수수익을 다음과 같이 정의하고 있다. ||선수수익이란 대가의 수입은 이루어졌으나 수익의 귀속시기가 차기 이후인 것을 말한다. 선수수익은 일종의 부채(負債)이긴 하지만, 원칙적으로는 금전으로 변제되는 부채가 아니라, 일반적으로 계속적인 용역의 제공을 통하여 변제되는 부채이다. 선수수익으로 처리해야 할 대상으로는 영업외수익항목인 이자수익의 선수금액 등이 있다.|| http://terms.naver.com/item.nhn?dirId=407&docId=808 이재학은 2005-06-15 일에 게임에 대한 결제를 하였다. 결제는 2005-08-05일까지로 하였다. 이때 2005-08-05일 까지는 부채로 남았지만 미리 결제를 하였으므로 수익이 될 수가 있다. 이런 개념을 선수수익이라고 한다. 만약 다음과 같은 테이블이 있다고 가정해 보자. {{{ 시작일 종료일 --------- -------- 20050615 20050805 }}} 그럼 결과는 다음과 같아야 한다. 결제는 06월에 했으며, 적용되는 월은 각각06, 07, 08월이다. {{{ 시작일 종료일 결제 적용 ---------- ---------- ---- ---- 20050615 20050630 06 06 20050701 20050731 06 07 20050801 20050805 06 08 }}} ==== 테스트데이터 ==== {{{ CREATE TABLE #temp( AccountID varchar(20) , BeginDT char(8) , EndDT char(8) ) INSERT #temp VALUES('yasicom', '20050615', '20050805') INSERT #temp VALUES('yangdb', '20050515', '20050605') INSERT #temp VALUES('endless', '20060101', '20060601') INSERT #temp VALUES('mkex', '20070513', '20070730') GO }}} ==== 처리 SQL문 ==== {{{ --쿼리 WITH Dumy(CF) AS ( SELECT 0 CF UNION ALL SELECT CF + 1 FROM Dumy WHERE CF + 1 <= 12 --1년치만계산함. ), MM(CF) AS ( SELECT CF FROM Dumy ) SELECT AccountID 계정 , YYYYMM + RIGHT('00' + BeginDD, 2) 시작일 , YYYYMM + CASE WHEN RIGHT(YYYYMM, 2) <> SUBSTRING(EndDT, 5, 2) THEN RIGHT('00' + EndDD, 2) ELSE RIGHT(EndDT, 2) END 종료일 , SUBSTRING(BeginDT, 5, 2) 결제 , RIGHT(YYYYMM, 2) 적용 FROM ( SELECT CONVERT(CHAR(6),DATEADD(mm, CF, BeginDT),112) YYYYMM , CONVERT(VARCHAR(2), CASE WHEN CF = 0 THEN DATEPART(dd, BeginDT) ELSE 1 END) BeginDD , CONVERT(VARCHAR(2), CASE WHEN CONVERT(CHAR(6), EndDT, 112) = CONVERT(CHAR(6), DATEADD(dd,-1, CONVERT(CHAR(6), DATEADD(mm,CF + 1, BeginDT),112) + '01' ),112) THEN DATEPART(dd,EndDT) ELSE DATEPART(dd, DATEADD(dd, -1, CONVERT(CHAR(6),DATEADD(mm,CF + 1, BeginDT), 112)+'01')) END) EndDD , BeginDT , EndDT , AccountID FROM #temp A CROSS JOIN (SELECT CF FROM MM) B WHERE CF <= DATEDIFF(mm, BeginDT, EndDT) ) T ORDER BY 계정, 시작일 }}} ==== CTE vs Cusor(or Loop) ==== 다음의 URL은 CTE 성능에 대한 테스트를 진행한 것을 정리해 논 것이다. http://www.sqlservercentral.com/articles/T-SQL/2926/ 그래프만 봐도 알겠지만, Loop를 이용한 재귀쿼리의 솔루션이 성능이 더 좋은 것을 알 수 있다. 이 문서에서는 재귀쿼리를 이용한 솔루션도 있다는 것을 참고하라고 만든 것이며, 성능 테스트는 각자 알아서 해보는 것이 좋을 듯..