SQL Server 2000
我有一张表格列出了可以销售特定产品的月份。
ProductCode MonthNum MonthName
XXX 1 January
XXX 2 February
YYY 1 January
YYY 3 March
YYY 5 May
ZZZ 6 June
ZZZ 7 July
我需要构建一个允许我传递一些参数的查询:
ProductCode
LatestMonthNum
LatestYear
FutureForecast
这将允许我构建一组数据列表,其中总行数基于FutureForecast值的数量,行的值将超出传递的LatestMonthNum和LatestYear参数值。
例如,如果我将以下值传递给查询:
ProductCode YYY
LatestMonthNum 5
LatestYear 2012
FutureForecast 5
我的数据如下:
ProductCode MonthNum Year
YYY 1 2013
YYY 3 2013
YYY 5 2013
YYY 1 2014
YYY 3 2014
答案 0 :(得分:0)
喜欢这个吗?
Select * From
(SELECT ProductCode, MonthNum, Year, RANK() OVER
(PARTITION BY ProductCode ORDER BY
CAST('1/' + CAST(MonthNum AS varchar) + '/' + CAST(Year AS varchar)
AS datetime)) AS 'RANK'
FROM dbo.MyTable
WHERE (ProductCode = @productcode) AND (MonthNum > @monthnum) AND
(Year > @latestyear)) tbl Where tbl.Rank <= @futureforcast
您的year
列在哪里?
答案 1 :(得分:0)
我将在未来创建一个包含月份和年份的表格(类似于数字表格):
CREATE TABLE future (month int, year int);
DECLARE @m int;
SET @m = 1;
DECLARE @y int;
SET @y = 2000;
WHILE (@y < 2200) -- will my brain be in a jar by now?
BEGIN
WHILE (@m < 13)
BEGIN
INSERT INTO future (month, year) VALUES (@m, @y);
SET @m += 1;
END
SET @m = 1;
SET @y += 1;
END;
然后您可以加入您的产品表与未来!
SELECT TOP @FutureForecast
p.ProductCode, p.MonthNum, f.[year]
FROM Products AS p
JOIN future AS f ON f.[month] = p.MonthNum
WHERE
p.ProductCode = @ProductCode
AND (p.MonthNum > @LatestMonthNum OR f.[year] > @LatestYear)
ORDER BY f.[year], p.MonthNum
答案 2 :(得分:0)
我相信这应该有效。您可以将循环转换为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+)我在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