在 SQL Server 中查找给定 12 个月内 6 个月的最高连续期间

Posted

技术标签:

【中文标题】在 SQL Server 中查找给定 12 个月内 6 个月的最高连续期间【英文标题】:Find highest consecutive period of 6 months within given 12 months in SQL Server 【发布时间】: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

【问题讨论】:

【参考方案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

【讨论】:

以上是关于在 SQL Server 中查找给定 12 个月内 6 个月的最高连续期间的主要内容,如果未能解决你的问题,请参考以下文章

如何从 sql server 2008 中具有不同 TaskIds 的表中查找日期?

SQL Server 按过去 24 小时、上周和上个月对促销进行分组,并按周降序排序

如何在 SQL Server 中删除不精确的重复项

如何通过 SQL Server 获取特定时间段的数据

如何在n个月内使用sql(无程序)获取每个月的第一天和最后一天

在 Bigquery 中计算过去 3 个月内活跃的供应商数量