【问题标题】:Calculate rolling month value in SQL Server在 SQL Server 中计算滚动月份值
【发布时间】:2010-08-12 12:29:52
【问题描述】:

我在 SQL Server 2005 数据库中有一个包含以下列的表:

Id,ProductName,Year,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec

我需要做的是计算产品的平均 ROLLING 值。

例如,如果名为“汽车”的产品在表中有 2 行(2009 年和 2010 年),我想计算 2009 年 8 月至 2010 年 8 月或 2009 年 3 月至 2010 年 3 月的平均值。

完成此任务的最佳方法是什么?

【问题讨论】:

  • 如果您将这些列作为表中的行,则更容易获得您期望的值。
  • 也许使用合适的数据模型?带有月份名称的列只是糟糕设计的尖叫;这些列应该是 ID、ProductName、Year、Month。那么各种计算都会变得简单。
  • 为什么不只存储日期而不是年份和月份?如果是一个月的最后一天,您可以更轻松地进行其他时间计算(每日平均值)。
  • 好吧,伙计们,我知道它看起来像一个糟糕的设计,但它以您看到的方式完成的原因是该表被渲染引擎使用,该渲染引擎为 CRUD 操作渲染网页。由于用户界面应该看起来像这样(每个月的文本字段),基础表结构必须像示例中一样。

标签: sql sql-server


【解决方案1】:

使用Sql Server 2005,可以看看UNPIVOT

将它们放回它们所属的行后,您就可以开始处理数据了。

类似

DECLARE @Table TABLE(
        Id INT,
        ProductName VARCHAR(20),
        [Year] INT,
        Jan FLOAT,
        Feb FLOAT,
        Mar FLOAT,
        Apr FLOAT,
        May FLOAT,
        Jun FLOAT,
        Jul FLOAT,
        Aug FLOAT,
        Sep FLOAT,
        Oct FLOAT,
        Nov FLOAT,
        [Dec] FLOAT
)

INSERT INTO @Table SELECT 1,'Car',2009,1,2,3,4,5,6,7,8,9,10,11,12
INSERT INTO @Table SELECT 1,'Car',2010,1,2,3,4,5,6,7,8,9,10,11,12

SELECT  Id,
        ProductName,
        CAST(YearMonth + ' ' + CAST([Year] AS VARCHAR(4)) AS DATETIME) MonthDate, 
        Vals
FROM    (
            SELECT  Id,ProductName,[Year],Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,[Dec]
            FROM    @Table
        ) tbl
        UNPIVOT (Vals FOR YearMonth IN (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,[Dec])) as unpvt

【讨论】:

  • 感谢您的回答!这正是我想要的!
【解决方案2】:

这是一个可行的解决方案

WITH MyProducts AS
    (
    SELECT [Id], [ProductName],
        CAST([MONTH] + ' 1, ' + CAST([Year] AS varchar) AS datetime) as [MyDate], [MyValues]
    FROM ( SELECT Id,ProductName,[Year],[Jan],[Feb],[Mar],[Apr],[May],[Jun],[Jul],[Aug],[Sep],[Oct],[Nov],[Dec]
            FROM [SourceTable] ) MyTable
    UNPIVOT ([MyValues] FOR [Month] IN
        ([Jan],[Feb],[Mar],[Apr],[May],[Jun],[Jul],[Aug],[Sep],[Oct],[Nov],[Dec])) AS [pivot]
    )

SELECT mp1.[ProductName], mp1.[MyDate], AVG(mp2.[MyValues]) AS MyValues
FROM [MyProducts] AS mp1
JOIN [MyProducts] AS mp2 ON mp2.MyDate BETWEEN DATEADD(MM, -11, mp1.[MyDate]) AND mp1.[MyDate]
WHERE mp1.[MyDate] BETWEEN '3/1/2010' AND '8/1/2010'
GROUP BY mp1.[ProductName], mp1.[MyDate]
ORDER BY mp1.[ProductName], mp1.[MyDate]

【讨论】:

    猜你喜欢
    • 2018-01-05
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多