I'm looking to use a cursor to loop through some customer contract date records to produce a list of all month/years that the customer had within that contract. I'm not even sure if a Cursor is the right solutuion.. But here it is anyway! The topic of Cursors being fairly new to me ..
My data is stored as below;
ContractStartDate ContractEndDate CustomerID Country
01-10-2016 01-02-2017 1234 UK
01-12-2016 01-03-2017 5678 UK
And I'm looking to display it as below;
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
Script so far below;
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
If you are not heart set on using cursors, here's a different approach.
I've set up a reference calendar, joined to your data, and returned all that sit between the start/end dates. The limit of the way I have done it, is that there is a maximum range of 2048 months ( i limited to 600 here). If you need more, then there are ways to overcome that limitation.
-- 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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.