可能行的SQL Server数据查询

时间:2012-02-21 19:16:47

标签: sql sql-server-2000

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

3 个答案:

答案 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