【问题标题】:Obtain AVG from December to December SQL获取12月到12月SQL的AVG
【发布时间】:2018-09-12 07:48:05
【问题描述】:

我有这张表(示例):

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

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

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

【问题讨论】:

  • 现在我刚刚有了在一个临时表中插入所有十二月的想法:SELECT * FROM demo WHERE (RIGHT(Period,2)) = '12'' 然后对示例表进行左连接,然后尝试使用它
  • 您使用的是哪个数据库?顺便说一句,我可以反对将年度金额存储在表中,因为它是从该表中的其他数据得出的数量。如果您必须在某处修改金额值会怎样?然后你必须再做一次更新。
  • 您如何计算年度金额仍不清楚,因为当我尝试计算年度金额时,我得到的金额与给定值不同。
  • @TimBiegeleisen 我同意。明确引入更新异常。另外,Period 属性的数据类型是什么?我只是问因为WHERE(RIGHT(Period,2))='12' 的例子有点尴尬。如果将其视为日期或简单的数字,则简单的WHERE 范围会更容易。 (即 201712
  • @Kang 它被视为 varchar 但我可以将其更改为日期

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


【解决方案1】:

您可以尝试以下更新。在这里,我们强制将上个月包含在下一年中,因此可能会有包含最多 13 个月的时期(按硬币)。请注意,我将AmountAnnualAmount 数据类型更改为DECIMAL(因为您使用的是小数而不仅仅是整数)。此外,12 月份用于 2 个不同的平均值(当前和明年),在此查询中,我们将更新其为当年的 AnnualAmount。

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)。在这种情况下,最好将此值保存在单独的汇总表中(按年份和硬币),或者只计算它以显示而不实际存储。

【讨论】:

    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-03
      • 1970-01-01
      • 1970-01-01
      • 2020-07-14
      • 1970-01-01
      • 2022-01-04
      • 1970-01-01
      • 2023-03-03
      相关资源
      最近更新 更多