【问题标题】:Find highest consecutive period of 6 months within given 12 months in SQL Server在 SQL Server 中查找给定 12 个月内 6 个月的最高连续期间
【发布时间】:2017-12-10 21:04:09
【问题描述】:

我正在为我们公司构建采购/重新订购计划算法。给定以下数据集,我将如何选择具有最高组合值的 6 个月期间? (例如 1 月至 6 月、2 月至 7 月、3 月至 8 月、4 月至 9 月等)

║ 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

【问题讨论】:

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


    【解决方案1】:

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

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

    此外,上面的数据最好用行而不是列来表示,下面的例子 UNPIVOT 就是上面的数据,如果做为行你可以跳过 unpivot

    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 个月。

    【讨论】:

      【解决方案2】:

      我可能会将月份转换为数字并添加一个表月份,其中包含 id 和 name 列,编号为 1..12。然后,假设这是过去 12 个月的需求历史,我将计算每个月的过去 6 个月的需求,并选择按累积需求降序排列的前 1 个。

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

      【讨论】:

        【解决方案3】:

        主要问题是您提出了部分问题。您应该使用少量样本数据发布正确的表格设计。

        这与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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-11-24
          • 1970-01-01
          • 2019-04-09
          • 2019-01-04
          • 1970-01-01
          • 2021-07-21
          • 1970-01-01
          相关资源
          最近更新 更多