TSQL - 计算植物和年份的价值超过几个月

TSQL - Calculate values for plants and years over months

我有以下 Excel 计算要复制到 T-SQL 语句:

此 Excel 以相同的格式导入到 SQL table (SQL Server 2012),另外还有两个用于工厂和年份的列。

下面是我用于报告的 SQL 视图。如您所见,月份变成了行,值列变成了行:

+---------+------+-------+------+--------+
|  Plant  | Year | Month |  A   |   B    |
+---------+------+-------+------+--------+
| Plant X | 2019 |     1 |  526 | 16     |
| Plant X | 2019 |     2 |  786 | 54     |
| Plant X | 2019 |     3 | 1800 | 85     |
| Plant X | 2019 |     4 | 9780 | 15     |
| Plant X | 2019 |     5 | 9780 | (null) |
| Plant Y | 2019 |     1 | 4080 | 128    |
| Plant Y | 2019 |     2 | 1387 | 179    |
+---------+------+-------+------+--------+

这是上面 sql 视图的 Fiddle

CREATE TABLE Test
    ([Plant] varchar(13), [Year] int, [Month] int, [A] decimal(18,2), [B] decimal(18,2))
;

INSERT INTO Test
    ([Plant], [Year], Month, A, B)
VALUES
    ('Plant X', 2019,1,526 ,16 ),
    ('Plant X', 2019,2,786 ,54),
    ('Plant X', 2019,3, 1800,85),
    ('Plant X', 2019,4, 9780,15),
    ('Plant X', 2019,5, 9780,NULL),
    ('Plant Y', 2019,1,4080 ,128 ),
    ('Plant Y', 2019,2,1387 ,179)
;

是否可以在我的 SQL 视图中进行计算,如上图 Excel 所示?如果是,你能举个例子吗?

因为我也有 SQL table 中的数据,就像 Excel 结构(以月份为列)那样以该格式进行计算更有意义?

谢谢。

这是一个必须取消透视某些列并在另一列上透视的问题。为了逆透视,我使用了一个 CROSS APPLY 和一个非常通用的 table values constructor (与逆透视运算符不同)。我还使用交叉表方法来透视数据。

SELECT  Plant, [Year], colName,
    SUM(CASE WHEN [Month] = 1 THEN colValue END),
    SUM(CASE WHEN [Month] = 2 THEN colValue END),
    SUM(CASE WHEN [Month] = 3 THEN colValue END),
    SUM(CASE WHEN [Month] = 4 THEN colValue END),
    SUM(CASE WHEN [Month] = 5 THEN colValue END),
    SUM(CASE WHEN [Month] = 6 THEN colValue END),
    SUM(CASE WHEN [Month] = 7 THEN colValue END)
FROM Test
CROSS APPLY( VALUES( 'A', A),( 'B', B)) AS x(colName, colValue)
GROUP BY Plant, [Year], colName
ORDER BY Plant, [Year], colName;

您也可以通过在 SQL 中使用 PIVOT 和 UNPIVOT 来实现。

SELECT [Plant]
  ,[Year]
  ,[newColumn]
  ,SUM([1]) [1]
  ,SUM([2]) [2]
  ,SUM([3]) [3]
  ,SUM([4]) [4]
  ,SUM([5]) [5]
FROM [Test]
UNPIVOT(Orders FOR newColumn IN (
          A
         ,B
        )) AS unpvt
PIVOT(SUM([Orders]) FOR [Month] IN (
         [1]
        ,[2]
        ,[3]
        ,[4]
        ,[5]
        )) AS PivotTable
GROUP BY [Plant]
  ,[Year]
  ,[newColumn]

以快速的方式和您的示例 table,它可能是这样的:

select t.*
    , Calculated = (
        select cast(round(sum(B) * 1000000 / sum(A), 0) as int)
        from Test
        where Plant = t.Plant
            and [Year] = t.[Year]
            and [Month] <= t.[Month]
        having sum(A) <> 0
        )
from Test t