从12月到12月获取AVG SQL

时间:2018-04-03 04:39:52

标签: sql sql-server tsql join sql-update

我有这张桌子(例子):

http://www.sqlfiddle.com/#!9/412b11/1

我需要根据年份在AnualAmount列中插入全年+去年12月的平均值,这是我必须使用示例数据获得的结果:

Example Result

因此,在2018年的所有时期,我必须在AnualAmount中插入全年的AVG +去年12月的金额,以及其他硬币和年份等等。

2 个答案:

答案 0 :(得分:2)

有点笨重,但我认为它有效

declare @T table (Period int, Coin varchar(3), Amount int, AnualAmount varchar(4));
INSERT INTO @T (Period, Coin, Amount, AnualAmount) VALUES
    (201701, 'MXP', 13.5, NULL),
    (201702, 'MXP', 14.5, NULL),
    (201703, 'MXP', 15.5, NULL),
    (201704, 'MXP', 16.5, NULL),
    (201705, 'MXP', 17.5, NULL),
    (201706, 'MXP', 18.5, NULL),
    (201707, 'MXP', 19.5, NULL),
    (201708, 'MXP', 20.5, NULL),
    (201709, 'MXP', 21.5, NULL),
    (201710, 'MXP', 22.5, NULL),
    (201711, 'MXP', 23.5, NULL),
    (201712, 'MXP', 24.5, NULL),
    (201801, 'MXP', 25.5, NULL),
    (201802, 'MXP', 26.5, NULL),
    (201803, 'MXP', 27.5, NULL),
    (201804, 'MXP', 28.5, NULL),
    (201805, 'MXP', 29.5, NULL),
    (201806, 'MXP', 30.5, NULL),
    (201807, 'MXP', 31.5, NULL),
    (201808, 'MXP', 32.5, NULL),
    (201809, 'MXP', 33.5, NULL),
    (201810, 'MXP', 34.5, NULL),
    (201811, 'MXP', 35.5, NULL),
    (201812, 'MXP', 36.5, NULL),
    (201701, 'COP', 37.5, NULL),
    (201702, 'COP', 38.5, NULL),
    (201703, 'COP', 39.5, NULL),
    (201704, 'COP', 40.5, NULL),
    (201705, 'COP', 41.5, NULL),
    (201706, 'COP', 42.5, NULL),
    (201707, 'COP', 43.5, NULL),
    (201708, 'COP', 44.5, NULL),
    (201709, 'COP', 45.5, NULL),
    (201710, 'COP', 46.5, NULL),
    (201711, 'COP', 47.5, NULL),
    (201712, 'COP', 48.5, NULL),
    (201801, 'COP', 49.5, NULL),
    (201802, 'COP', 50.5, NULL),
    (201803, 'COP', 51.5, NULL),
    (201804, 'COP', 52.5, NULL),
    (201805, 'COP', 53.5, NULL),
    (201806, 'COP', 54.5, NULL),
    (201807, 'COP', 55.5, NULL),
    (201808, 'COP', 56.5, NULL),
    (201809, 'COP', 57.5, NULL),
    (201810, 'COP', 58.5, NULL),
    (201811, 'COP', 59.5, NULL),
    (201812, 'COP', 60.5, NULL),
    (201701, 'REA', 61.5, NULL),
    (201702, 'REA', 62.5, NULL),
    (201703, 'REA', 63.5, NULL),
    (201704, 'REA', 64.5, NULL),
    (201705, 'REA', 65.5, NULL),
    (201706, 'REA', 66.5, NULL),
    (201707, 'REA', 67.5, NULL),
    (201708, 'REA', 68.5, NULL),
    (201709, 'REA', 69.5, NULL),
    (201710, 'REA', 70.5, NULL),
    (201711, 'REA', 71.5, NULL),
    (201712, 'REA', 72.5, NULL),
    (201801, 'REA', 73.5, NULL),
    (201802, 'REA', 74.5, NULL),
    (201803, 'REA', 75.5, NULL),
    (201804, 'REA', 76.5, NULL),
    (201805, 'REA', 77.5, NULL),
    (201806, 'REA', 78.5, NULL),
    (201807, 'REA', 79.5, NULL),
    (201808, 'REA', 80.5, NULL),
    (201809, 'REA', 81.5, NULL),
    (201810, 'REA', 82.5, NULL),
    (201811, 'REA', 83.5, NULL),
    (201812, 'REA', 84.5, NULL);
declare @D table (Period int);
INSERT INTO @D (Period) values
    (201712),
    (201801),
    (201802),
    (201803),
    (201804),
    (201805),
    (201806),
    (201807),
    (201808),
    (201809),
    (201810),
    (201811),
    (201812);
select t.Coin, t.Period, t.Amount 
     , AVG(t.Amount) over (partition by t.Coin) as Annual     
from @T t
join @D d
on t.Period = d.Period 
union all 
select t.Coin, t.Period, t.Amount  
     , null    
from @T t
left join @D d
on t.Period = d.Period 
where d.Period is null
order by Coin, Period;

Coin Period      Amount      Annual
---- ----------- ----------- -----------
COP  201701      37          NULL
COP  201702      38          NULL
COP  201703      39          NULL
COP  201704      40          NULL
COP  201705      41          NULL
COP  201706      42          NULL
COP  201707      43          NULL
COP  201708      44          NULL
COP  201709      45          NULL
COP  201710      46          NULL
COP  201711      47          NULL
COP  201712      48          54
COP  201801      49          54
COP  201802      50          54
COP  201803      51          54
COP  201804      52          54
COP  201805      53          54
COP  201806      54          54
COP  201807      55          54
COP  201808      56          54
COP  201809      57          54
COP  201810      58          54
COP  201811      59          54
COP  201812      60          54
MXP  201701      13          NULL
MXP  201702      14          NULL
MXP  201703      15          NULL
MXP  201704      16          NULL
MXP  201705      17          NULL
MXP  201706      18          NULL
MXP  201707      19          NULL
MXP  201708      20          NULL
MXP  201709      21          NULL
MXP  201710      22          NULL
MXP  201711      23          NULL
MXP  201712      24          30
MXP  201801      25          30
MXP  201802      26          30
MXP  201803      27          30
MXP  201804      28          30
MXP  201805      29          30
MXP  201806      30          30
MXP  201807      31          30
MXP  201808      32          30
MXP  201809      33          30
MXP  201810      34          30
MXP  201811      35          30
MXP  201812      36          30
REA  201701      61          NULL
REA  201702      62          NULL
REA  201703      63          NULL
REA  201704      64          NULL
REA  201705      65          NULL
REA  201706      66          NULL
REA  201707      67          NULL
REA  201708      68          NULL
REA  201709      69          NULL
REA  201710      70          NULL
REA  201711      71          NULL
REA  201712      72          78
REA  201801      73          78
REA  201802      74          78
REA  201803      75          78
REA  201804      76          78
REA  201805      77          78
REA  201806      78          78
REA  201807      79          78
REA  201808      80          78
REA  201809      81          78
REA  201810      82          78
REA  201811      83          78
REA  201812      84          78

答案 1 :(得分:1)

您可以尝试以下更新。在这里,我们强制将前一个月纳入下一年,因此可能有一段时间(按硬币计算),包括长达13个月。请注意,我将AmountAnnualAmount数据类型更改为DECIMAL(因为您使用的是小数而不仅仅是整数)。此外,12月份用于2个不同的平均值(当前和明年),在此查询中,我们正在更新当前年份的年度安装量。

IF OBJECT_ID('tempdb..#Table') IS NOT NULL
    DROP TABLE #Table

CREATE TABLE #Table (
    Period int, 
    Coin varchar(3), 
    Amount DECIMAL(8,2), 
    AnnualAmount DECIMAL(8,2))

INSERT INTO #Table (Period, Coin, Amount, AnnualAmount) 
VALUES
    (201701, 'MXP', 13.5, NULL),
    (201702, 'MXP', 14.5, NULL),
    (201703, 'MXP', 15.5, NULL),
    (201704, 'MXP', 16.5, NULL),
    (201705, 'MXP', 17.5, NULL),
    (201706, 'MXP', 18.5, NULL),
    (201707, 'MXP', 19.5, NULL),
    (201708, 'MXP', 20.5, NULL),
    (201709, 'MXP', 21.5, NULL),
    (201710, 'MXP', 22.5, NULL),
    (201711, 'MXP', 23.5, NULL),
    (201712, 'MXP', 24.5, NULL),
    (201801, 'MXP', 25.5, NULL),
    (201802, 'MXP', 26.5, NULL),
    (201803, 'MXP', 27.5, NULL),
    (201804, 'MXP', 28.5, NULL),
    (201805, 'MXP', 29.5, NULL),
    (201806, 'MXP', 30.5, NULL),
    (201807, 'MXP', 31.5, NULL),
    (201808, 'MXP', 32.5, NULL),
    (201809, 'MXP', 33.5, NULL),
    (201810, 'MXP', 34.5, NULL),
    (201811, 'MXP', 35.5, NULL),
    (201812, 'MXP', 36.5, NULL),
    (201701, 'COP', 37.5, NULL),
    (201702, 'COP', 38.5, NULL),
    (201703, 'COP', 39.5, NULL),
    (201704, 'COP', 40.5, NULL),
    (201705, 'COP', 41.5, NULL),
    (201706, 'COP', 42.5, NULL),
    (201707, 'COP', 43.5, NULL),
    (201708, 'COP', 44.5, NULL),
    (201709, 'COP', 45.5, NULL),
    (201710, 'COP', 46.5, NULL),
    (201711, 'COP', 47.5, NULL),
    (201712, 'COP', 48.5, NULL),
    (201801, 'COP', 49.5, NULL),
    (201802, 'COP', 50.5, NULL),
    (201803, 'COP', 51.5, NULL),
    (201804, 'COP', 52.5, NULL),
    (201805, 'COP', 53.5, NULL),
    (201806, 'COP', 54.5, NULL),
    (201807, 'COP', 55.5, NULL),
    (201808, 'COP', 56.5, NULL),
    (201809, 'COP', 57.5, NULL),
    (201810, 'COP', 58.5, NULL),
    (201811, 'COP', 59.5, NULL),
    (201812, 'COP', 60.5, NULL),
    (201701, 'REA', 61.5, NULL),
    (201702, 'REA', 62.5, NULL),
    (201703, 'REA', 63.5, NULL),
    (201704, 'REA', 64.5, NULL),
    (201705, 'REA', 65.5, NULL),
    (201706, 'REA', 66.5, NULL),
    (201707, 'REA', 67.5, NULL),
    (201708, 'REA', 68.5, NULL),
    (201709, 'REA', 69.5, NULL),
    (201710, 'REA', 70.5, NULL),
    (201711, 'REA', 71.5, NULL),
    (201712, 'REA', 72.5, NULL),
    (201801, 'REA', 73.5, NULL),
    (201802, 'REA', 74.5, NULL),
    (201803, 'REA', 75.5, NULL),
    (201804, 'REA', 76.5, NULL),
    (201805, 'REA', 77.5, NULL),
    (201806, 'REA', 78.5, NULL),
    (201807, 'REA', 79.5, NULL),
    (201808, 'REA', 80.5, NULL),
    (201809, 'REA', 81.5, NULL),
    (201810, 'REA', 82.5, NULL),
    (201811, 'REA', 83.5, NULL),
    (201812, 'REA', 84.5, NULL);


;WITH ParsedDates AS
(
    SELECT
        T.*,
        Year = T.Period / 100,
        Month = T.Period % 100
    FROM
        #Table AS T
),
CoinPeriods AS
(
    SELECT
        P.Amount,
        P.Coin,
        P.YEAR,
        P.Month
    FROM
        ParsedDates AS P
    UNION ALL
    SELECT
        N.Amount,
        N.Coin,
        Year = N.YEAR + 1, -- Force previous year's months to be included in next year calculation
        N.Month
    FROM
        ParsedDates AS N
    WHERE
        N.Month = 12
),
AnnualAmounts AS
(
    SELECT
        P.Coin,
        P.Year,
        AnnualAmount = AVG(P.Amount)
    FROM
        CoinPeriods AS P
    GROUP BY
        P.Coin,
        P.Year
)
UPDATE T SET
    AnnualAmount = A.AnnualAmount
FROM
    #Table AS T
    INNER JOIN AnnualAmounts AS A ON
        T.Coin = A.Coin AND
        T.Period / 100 = A.Year


/* 

SELECT * FROM #Table AS T

Results:

    Period  Coin    Amount  AnnualAmount
    201701  MXP 13.50   19.00
    201702  MXP 14.50   19.00
    201703  MXP 15.50   19.00
    201704  MXP 16.50   19.00
    201705  MXP 17.50   19.00
    201706  MXP 18.50   19.00
    201707  MXP 19.50   19.00
    201708  MXP 20.50   19.00
    201709  MXP 21.50   19.00
    201710  MXP 22.50   19.00
    201711  MXP 23.50   19.00
    201712  MXP 24.50   19.00
    201801  MXP 25.50   30.50
    201802  MXP 26.50   30.50
    201803  MXP 27.50   30.50
    201804  MXP 28.50   30.50
    201805  MXP 29.50   30.50
    201806  MXP 30.50   30.50
    201807  MXP 31.50   30.50
    201808  MXP 32.50   30.50
    201809  MXP 33.50   30.50
    201810  MXP 34.50   30.50
    201811  MXP 35.50   30.50
    201812  MXP 36.50   30.50
    201701  COP 37.50   43.00
    201702  COP 38.50   43.00
    201703  COP 39.50   43.00
    201704  COP 40.50   43.00
    201705  COP 41.50   43.00
    201706  COP 42.50   43.00
    201707  COP 43.50   43.00
    201708  COP 44.50   43.00
    201709  COP 45.50   43.00
    201710  COP 46.50   43.00
    201711  COP 47.50   43.00
    201712  COP 48.50   43.00
    201801  COP 49.50   54.50
    201802  COP 50.50   54.50
    201803  COP 51.50   54.50
    201804  COP 52.50   54.50
    201805  COP 53.50   54.50
    201806  COP 54.50   54.50
    201807  COP 55.50   54.50
    201808  COP 56.50   54.50
    201809  COP 57.50   54.50
    201810  COP 58.50   54.50
    201811  COP 59.50   54.50
    201812  COP 60.50   54.50
    201701  REA 61.50   67.00
    201702  REA 62.50   67.00
    201703  REA 63.50   67.00
    201704  REA 64.50   67.00
    201705  REA 65.50   67.00
    201706  REA 66.50   67.00
    201707  REA 67.50   67.00
    201708  REA 68.50   67.00
    201709  REA 69.50   67.00
    201710  REA 70.50   67.00
    201711  REA 71.50   67.00
    201712  REA 72.50   67.00
    201801  REA 73.50   78.50
    201802  REA 74.50   78.50
    201803  REA 75.50   78.50
    201804  REA 76.50   78.50
    201805  REA 77.50   78.50
    201806  REA 78.50   78.50
    201807  REA 79.50   78.50
    201808  REA 80.50   78.50
    201809  REA 81.50   78.50
    201810  REA 82.50   78.50
    201811  REA 83.50   78.50
    201812  REA 84.50   78.50

*/

我同意Tim的意见,因为存储一个依赖于超过1行的计算列是一个糟糕设计的标志(更新一行的Amount将需要重新计算几个AnnualAmount那些)。在这种情况下,最好将此值保存在聚合单独的表中(按年份和硬币),或者只计算它以显示而不是实际存储。