Я считаю, что это должно работать.Вы могли бы превратить цикл в CTE (только для SQL 2005+), но я не уверен, что в этом случае вам это удастся.
CREATE TABLE #TempOrder
(Order INT IDENTITY (1,1), ProductCode VARCHAR(MAX), MonthNum INT)
INSERT INTO #TempOrder
SELECT ProductCode, MonthNum
FROM ProductTable
WHERE ProductCode = @ProductCode AND MonthNum > @LatestMonthNum
ORDER BY MonthNum DESC
--Increment the year from the start if it is already over the max stored
IF NOT EXISTS (SELECT 1 FROM #TempOrder)
SET @LatestYear = @LatestYear + 1
INSERT INTO #TempOrder
SELECT ProductCode, MonthNum
FROM ProductTable
WHERE ProductCode = @ProductCode AND MonthNum <= @LatestMonthNum
ORDER BY MonthNum DESC
DECLARE @MaxId
SELECT @MaxId = MAX(Id) FROM #TempOrder
CREATE TABLE #ForecastData (ProductCode VARCHAR(MAX), MonthNum INT, Year INT)
DECLARE @CurrentId INT
SET @CurrentId = 1
DECLARE @CurrentCount INT
SET @CurrentCount = 0
WHILE(@CurrentCount < @FutureForeCast)
BEGIN
INSERT INTO #ForecastData
SELECT ProductCode, MonthNum, @LatestYear
FROM #TempOrder
WHERE Id = @CurrentId
--Increment the Id, and if it's over the max in the table
--Reset to 1 and increment for a new year
SET @CurrentId = @CurrentId + 1
IF @CurrentId > @MaxId
BEGIN
SET @CurrentId = 1
SET @LatestYear = @LatestYear + 1
END
SET @CurrentCount = @CurrentCount + 1
END
SELECT #ForecastData
(Это решение только для SQL 2005+) IЯ чрезвычайно ржавый на CTE, но я подумал, что я бы тоже попробовал это как CTE.Это заменяет все сверху из CREATE TABLE #ForecastData .... down:
;
WITH ForecastData (ProductCode, MonthNum, Year)
AS
(
-- Anchor member definition
SELECT ProductCode, MonthNum, @LatestYear AS Year, Id AS LastId
FROM #TempOrder
WHERE Id = 1
UNION ALL
-- Recursive member definition
SELECT ProductCode, MonthNum,
CASE WHEN Id = 1 THEN Year + 1 ELSE Year,
Id AS LastId
FROM #TempOrder
JOIN ForecastData
ON Id = CASE
WHEN LastId = @MaxId THEN 1
ELSE LastId + 1
END
)
-- Statement that executes the CTE
SELECT *
FROM ForecastData;
GO