2017-10-10 68 views
0

我正在寻找使用游标来遍历某些客户合同日期记录以生成客户在该合同中所有月份/年份的列表。我甚至不确定一个光标是否是正确的solutuion ..但是,无论如何它都是!光标对我来说是相当新的。SQL游标使用

我的数据存储如下;

ContractStartDate ContractEndDate CustomerID Country 
01-10-2016   01-02-2017  1234   UK 
01-12-2016   01-03-2017  5678   UK 

而我正在寻找显示如下;

Customer Country Month Year 
1234  UK  Oct  2016 
1234  UK  Nov  2016 
1234  UK  Dec  2016 
1234  UK  Jan  2017 
1234  UK  Feb  2017 
5678  UK  Dec  2016 
5678  UK  Jan  2017 
5678  UK  Feb  2017 
5678  UK  Mar  2017 

脚本至今为止;

DECLARE 

@StartDate DATETIME, 
@EndDate DATETIME, 
@Customer nvarchar(30), 
@Country nvarchar(30), 
@Cursor  as CURSOR; 

SET @Cursor = CURSOR FOR 
SELECT DISTINCT f.ContractStartDate, f.ContractEndDate, c.Customer, c.Country 
FROM Contracts c 
    JOIN CustomerInfo i 
     ON c.CustomerID = i.ID 

OPEN @Cursor 
FETCH NEXT FROM @Cursor INTO @StartDate,@EndDate,@Customer,@Country;  

WHILE @@FETCH_STATUS = 0 
BEGIN 


SELECT DATENAME(MONTH, DATEADD(MONTH, x.number, @StartDate)) AS MonthName, DATENAME(YEAR, DATEADD(MONTH, x.number, @StartDate)) AS MonthName 
FROM master.dbo.spt_values x 
WHERE x.type = 'P'   
AND  x.number <= DATEDIFF(MONTH, @StartDate, @EndDate); 

END 

Close @Cursor 
DEALLOCATE @Cursor 
+0

看起来像SQLServer,请添加必要的标签,不同的引擎有不同的光标处理。 – bummi

+0

合同开始/结束日期是否始终在本月的第一天? – TZHX

+0

日期并不总是在开始/结束。 (现在也编辑标签,谢谢) – user2261755

回答

0

如果你对使用光标没有心设置,这是一种不同的方法。

我已经设置了参考日历,加入了您的数据,并返回了开始/结束日期之间的所有内容。 我已经做到了这一点的限制是,有一个2048个月的最大范围(我限制在这里600)。如果你需要更多,那么有办法克服这个限制。

-- Set up for testing 

create table test.contracts(
    ContractStartDate datetime, ContractEndDate datetime, CustomerID int ,Country nvarchar(2) 
) 

insert into test.contracts(ContractStartDate,ContractEndDate,CustomerID,Country) 
Values(convert(datetime,'2016-10-01'), CONVERT(datetime,'2017-02-01'), 1234, 'UK') 
insert into test.contracts(ContractStartDate,ContractEndDate,CustomerID,Country) 
Values(convert(datetime,'2016-12-01'), CONVERT(datetime,'2017-03-01'), 5678, 'UK') 

-- Execute 
SELECT 
    C.*, cal.[Month] 
FROM test.contracts C 
     INNER JOIN 
    (
     SELECT dateadd(m,number,convert(datetime,'2000-01-01')) as [Month] 
     FROM master..[spt_values] 
     where type='p' and number BETWEEN 0 AND 600 
    ) as cal 
    ON C.ContractStartDate <= cal.Month and C.ContractEndDate >= cal.Month