SQL游标用法

时间:2017-10-10 14:36:22

标签: sql sql-server cursor

我希望使用游标循环浏览一些客户合约日期记录,以生成客户在该合约中所有月/年的列表。我甚至不确定Cursor是否是正确的解决方案..但无论如何它在这里!游标的主题对我来说还是比较新的..

我的数据存储如下;

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

1 个答案:

答案 0 :(得分: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