SQL计算"到日期"月份列的值

时间:2014-09-10 22:05:03

标签: sql sql-server-2008

SQL Afficianados,

必须有一条比我要走的道路更好的方式......

SQL Fiddle HERE

使用SQL Server 2008.简而言之,我有一个以月为列的表。即:

CREATE TABLE MyData (MyID VARCHAR(10), 
  JAN MONEY, FEB MONEY, MAR MONEY, APR MONEY, MAY MONEY, JUN MONEY,
  JUL MONEY, AUG MONEY, SEP MONEY, OCT MONEY, NOV MONEY, DEC MONEY);

给定N的月值(作为整数,其中1 = JAN和12 = DEC),我想计算从第一个月到第N个月的“To Date”值。

所以,鉴于这个简单的数据:

INSERT INTO MyData (MyID, JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC)
SELECT 'Rec1', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
UNION ALL SELECT 'Rec2', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
UNION ALL SELECT 'Rec3', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
;

我想传入任何月份值并添加正确的月份列。鉴于上面的示例数据,这里是基于传递的月份值的预期结果图表。

Month Value | Expected Result |
------------+------------------
1           | 3
2           | 9
3           | 18
4           | 30
5           | 45
6           | 63
7           | 84
8           | 108
9           | 135
10          | 165
11          | 198
12          | 234

我知道我可以用这样的CASE语句来做到这一点:

DECLARE @v_Month INT = 2

SELECT CASE
  WHEN @v_Month = 1 THEN SUM(JAN)
  WHEN @v_Month = 2 THEN SUM(JAN) + SUM(FEB)
  WHEN @v_Month = 2 THEN SUM(JAN) + SUM(FEB) + SUM(MAR)
  --You get the idea. The pattern would continue for the rest of the months.
  ELSE 0
END AS ToDateSum
FROM MyData

但是有更好的方法吗?教我,非常棒的SQL Server。

2 个答案:

答案 0 :(得分:1)

您可以使用unpivot将数据更改为更合适的形状。首先以这种方式存储它可能更有意义。

declare  @v_Month int = 2;

with u as (
  select
    myid, [month], amount
  from (
    select
      myid, jan [1], feb [2], mar [3], apr [4], may [5], jun [6], 
      jul [7], aug [8], sep [9], oct [10], nov [11], dec [12]
    from
      MyData
  ) p
  unpivot (
    amount for [month] in ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12])
  ) u
) select
  sum(amount)
from
  u
where
  [month] <= @v_Month;

Example SQLFiddle

如果要将数据保持在相同的结构中,可以稍微简化一下:

select
  sum(amount)
from (
  select
    myid, jan [1], feb [2], mar [3], apr [4], may [5], jun [6], 
    jul [7], aug [8], sep [9], oct [10], nov [11], dec [12]
  from
    MyData
) p
unpivot (
  amount for [month] in ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12])
) u
where
  [month] <= @v_Month;

答案 1 :(得分:0)

这样的事情会起作用:

declare @MyDesiredMonth int = 3

with normalized_view as
(
            select MyId , Month =  1 , Value = Jan from MyData
  UNION ALL select MyId , Month =  2 , Value = Feb from MyData
  UNION ALL ...
  UNION ALL select MyId , Month = 11 , Value = Nov from MyData
  UNION ALL select MyId , Month = 12 , Value = Dec from MyData
)
select MonthlyTotal = sum(Value)
from normalized_view t
where t.Month = @myDesiredMonth

或者,像这样:

declare @MyDesiredMonth int = 3

select MonthlyTotal = sum( case @MyDesiredMonth
                           when  1 then t.Jan
                           when  2 then t.Feb
                           ...
                           when 11 then t.Nov
                           when 12 then t.Dec
                           end
                         )
from MyTable t

任何一方都应该与执行计划合作可能会结束相似的事情。