Contents

[-]
1 선수수익이란?
2 테스트데이터
3 처리 SQL문
4 CTE vs Cusor(or Loop)


1 선수수익이란? #

네이버 용어 사전에는 선수수익을 다음과 같이 정의하고 있다.
선수수익이란 대가의 수입은 이루어졌으나 수익의 귀속시기가 차기 이후인 것을 말한다. 선수수익은 일종의 부채(負債)이긴 하지만, 원칙적으로는 금전으로 변제되는 부채가 아니라, 일반적으로 계속적인 용역의 제공을 통하여 변제되는 부채이다. 선수수익으로 처리해야 할 대상으로는 영업외수익항목인 이자수익의 선수금액 등이 있다.
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

2 테스트데이터 #

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

3 처리 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 계정, 시작일

4 CTE vs Cusor(or Loop) #

다음의 URL은 CTE 성능에 대한 테스트를 진행한 것을 정리해 논 것이다.
그래프만 봐도 알겠지만, Loop를 이용한 재귀쿼리의 솔루션이 성능이 더 좋은 것을 알 수 있다. 이 문서에서는 재귀쿼리를 이용한 솔루션도 있다는 것을 참고하라고 만든 것이며, 성능 테스트는 각자 알아서 해보는 것이 좋을 듯..
Retrieved from http://www.databaser.net/moniwiki/wiki.php/선수수익
last modified 2018-04-13 23:12:53