在SQL Server中,在给定的12个月内找到最长连续6个月的时间段

时间:2017-12-10 21:04:10

标签: sql sql-server sql-server-2008-r2

我正在为我们公司制定购买/重新订购计划算法。给定以下数据集,我如何选择具有最高组合值的6个月期间? (E.G. Jan-June,Feb-July,Mar-Aug,Apr-Sep等)

║ January ║ February ║ March ║ April ║ May ║ June ║ July ║ August ║ September ║ October ║ November ║ December ║
║ 5       ║ 2        ║ 6     ║ 2     ║ 5   ║ 4    ║ 8    ║ 5      ║ 6         ║ 4       ║ 3        ║ 2        ║

显然这可以通过以下方式实现,但我希望代码更灵活,因此我可以根据需要更改6或12的值。

(SELECT MAX(Details.Quantity)
      FROM 
    (VALUES 
    SUM(January, February, March, April, May, June),
    SUM(February, March, April, May, June, July),
    SUM(March, April, May, June, July, August),
    SUM(April, May, June, July, August, September),
    SUM(May, June, July, August, September, October),
    SUM(June, July, August, September, October, November),
    SUM(July, August, September, October, November, December)
    ) AS Details(Quantity)) 

   AS Max

3 个答案:

答案 0 :(得分:1)

先生。 Cat是对的,这是支持它的SQL。

  

我创建了一个表[MonthIds],它基本上是12行1月=> 1月,2月=> 2月...... 12月=> 12

此外,上述数据最好用Rows而不是Columns表示,下面的示例UNPIVOT是上面的数据,如果按行完成,则可以跳过univot

SELECT TOP 1 Month AS StartMonth
FROM (
    SELECT [Month],
        [Value],
        SUM([value]) OVER (
            ORDER BY MonthId ROWS BETWEEN CURRENT ROW
                    AND 6 FOLLOWING
            ) AS SumOverPeriod
    FROM (
        SELECT mi.Id AS MonthId,
            [Month],
            [Value]
        FROM (
            SELECT *
            FROM [Months]
            ) m
        UNPIVOT([Value] FOR [Month] IN (
                    [January],
                    [February],
                    [March],
                    [April],
                    [May],
                    [June],
                    [July],
                    [August],
                    [September],
                    [October],
                    [November],
                    [December]
                    )) AS u
        JOIN [MonthIds] mi ON mi.NAME = u.Month
        ) a
    ) s
ORDER BY SumOverPeriod DESC

此SQL将为您提供6个月的开始月

您可以更改 AND 6 FOLLOWING 并替换为您想要的任何数字。

请注意 如果将其更改为12,那么1月将始终是第1个月。

答案 1 :(得分:0)

我可能会将月份转换为数字,并添加一个带有列ID和名称的表格,编号为1..12。然后,假设这是一个过去12个月的需求历史记录,我将计算每个月的过去6个月的需求,并选择按累计需求下降排序的前1个。

如果这是一个持续的事情,您可以在另一个表中累积需求,然后每个月重新计算,以便您的数据是新鲜的。

答案 2 :(得分:0)

主要问题是你问了部分问题。你应该发布正确的表设计,只有很少的样本数据。

这个解决方案适用于sql server 2008及以下

 create table #t (January int,February int,March int,April int,May int
 ,June int,July int,August int,September int,October int,November int,December int)

 insert into #t VALUES
 (5,2,6,2,5,4,8, 5,6,4,3,2)

 declare @RangeMonth int=6

 ;with CTE as
 (
 select *,ROW_NUMBER() over(order by (select null))rn 
 from #t
  UNPIVOT([Value] FOR [Month] IN (
                    [January],
                    [February],
                    [March],
                    [April],
                    [May],
                    [June],
                    [July],
                    [August],
                    [September],
                    [October],
                    [November],
                    [December]
                    )) AS u
 )
 ,CTE1 AS(
 select [month], rn,value, sumValue from CTE c
 cross apply
 (
 select sum(value) sumValue from cte c1 
 where c1.rn>=c.rn and c1.rn<=c.rn+@RangeMonth
 )ca

 )
 ,CTE2 AS(
 select max(sumvalue)sumvalue from cte1 c1
 )
 ,CTE3 AS(
 select c.* from cte1 c
 cross apply(
 select sumvalue from cte2 c1 where c.sumvalue=c1.sumvalue
 )ca
 )
 select c.* from cte1 c
 cross apply(select * from cte3 c1 where c.rn>=c1.rn and c.rn<=c1.rn+@RangeMonth)ca

 drop table #t