使用 Pivot 计算最近两天的数据变化百分比

Using Pivot to Calculate % data change in last two days

我有一个 table,其中包含每天收集的一组数据(我使用 SQL Server 2016)

Date        A     B     C    D
2017/5/22   1.1   2.1  3.1   4.1
2017/5/21   1.0   2.0  3.0   4.0
2017/5/20   0.9   1.9  2.9   3.9
2017/5/19   1.0   2.0  3.0   4.0
2017/5/18   1.1   2.1  3.1   4.1

我正在尝试编写一个查询来显示最近两天的变化百分比,返回结果如下:

Field  Today   Yesterday  Change(%)
A       1.1       1.0       10.0%
B       2.1       2.0        5.0%
C       3.1       3.0        3.3%
D       4.1       4.0        2.5%

有没有快速的方法来做到这一点(我假设某个地方涉及到 pivot 但我真的无法解决这个问题)

这应该能满足您的需求:

select
    FieldValue                          as  [Field]
    , case FieldValue 
        when 'A'
            then ta
        when 'B'
            then tb
        when 'C'
            then tc
        when 'D'
            then td
        end                             as  [Today]
    , case FieldValue 
        when 'A'
            then ya
        when 'B'
            then yb
        when 'C'
            then yc
        when 'D'
            then yd
        end                             as  [Yesterday]
    , Change                            as  [Change(%)]
    from
    (select
        t1.a                            as  [ta]    -- today's A value
        , t1.b                          as  [tb]    -- today's B value
        , t1.c                          as  [tc]    -- today's C value
        , t1.d                          as  [td]    -- today's D value
        --, t1.e                        as  [te]    -- today's E value
        -- make sure to include the t1.e, t1.f etc. for other Fields too

        , y.a                           as  [ya]    -- yesterday's A value
        , y.b                           as  [yb]    -- yesterday's B value
        , y.c                           as  [yc]    -- yesterday's C value
        , y.d                           as  [yd]    -- yesterday's D value
        --, y.e                         as  [ye]    -- yesterday's E value
        -- make sure to include the y.e, y.f etc. for other Fields too

        , 100 / (y.a / (t1.a - y.a))    as  [A]     -- A's change since yesterday
        , 100 / (y.b / (t1.b - y.b))    as  [B]     -- B's change since yesterday
        , 100 / (y.c / (t1.c - y.c))    as  [C]     -- C's change since yesterday
        , 100 / (y.d / (t1.d - y.d))    as  [D]     -- D's change since yesterday
        --, 100 / (y.e / t1.e - y.e))   as  [E]     -- E's change since yesterday (INCLUDE this "E" alias in the list of columns from UNPIVOT)
        -- make sure to add calculations for your other fields here too

    from baseTable t1
        cross apply (select top 1 * 
                     from baseTable t2 
                     where t2.date < t1.date) y
    where t1.date = (select max(date) from baseTable)
    ) result
unpivot (
    Change for FieldValue in (a, b, c, d) --, e, f etc.) -- enumerate all column ALIASES used in the sub-select, where the CHANGE is calculated
    ) as unpvt

只需确保使用所有值扩展 CASE 语句和 UNPIVOT 列,并使用所有其他字段扩展 100 / (x.a / (t1.a - x.a))

我用来生成示例数据的脚本: (理想情况下你应该提供这个)

CREATE TABLE [dbo].[baseTable](
    [date] [date] NULL,
    [a] [numeric](18, 1) NULL,
    [b] [numeric](18, 1) NULL,
    [c] [numeric](18, 1) NULL,
    [d] [numeric](18, 1) NULL
)

GO
INSERT [dbo].[baseTable] ([date], [a], [b], [c], [d]) VALUES (CAST(N'2017-05-22' AS Date), CAST(1.1 AS Numeric(18, 1)), CAST(2.1 AS Numeric(18, 1)), CAST(3.1 AS Numeric(18, 1)), CAST(4.1 AS Numeric(18, 1)))
GO
INSERT [dbo].[baseTable] ([date], [a], [b], [c], [d]) VALUES (CAST(N'2017-05-21' AS Date), CAST(1.0 AS Numeric(18, 1)), CAST(2.0 AS Numeric(18, 1)), CAST(3.0 AS Numeric(18, 1)), CAST(4.0 AS Numeric(18, 1)))
GO
INSERT [dbo].[baseTable] ([date], [a], [b], [c], [d]) VALUES (CAST(N'2017-05-20' AS Date), CAST(0.9 AS Numeric(18, 1)), CAST(1.9 AS Numeric(18, 1)), CAST(2.9 AS Numeric(18, 1)), CAST(3.9 AS Numeric(18, 1)))
GO
INSERT [dbo].[baseTable] ([date], [a], [b], [c], [d]) VALUES (CAST(N'2017-05-19' AS Date), CAST(1.0 AS Numeric(18, 1)), CAST(2.0 AS Numeric(18, 1)), CAST(3.0 AS Numeric(18, 1)), CAST(4.0 AS Numeric(18, 1)))
GO
INSERT [dbo].[baseTable] ([date], [a], [b], [c], [d]) VALUES (CAST(N'2017-05-18' AS Date), CAST(1.1 AS Numeric(18, 1)), CAST(2.1 AS Numeric(18, 1)), CAST(3.1 AS Numeric(18, 1)), CAST(4.1 AS Numeric(18, 1)))
GO

我首先使用窗口函数得到结果,例如 row_number 来获取前 2 个日期,然后对 AB、[= 的列进行逆透视17=] 和 D 成行。完成后,您可以调整这些结果以获得最终所需的产品。

打破这个,我会开始使用 row_number:

select [Date], A, B, C, D,
  rn = row_number() over(order by [Date] desc) 
from #yourtable

这会为您的 table 中的每一行创建一个唯一的行 ID,您可以按日期对其进行排序以按照您想要的顺序生成日期。接下来,您需要将 ABCD 列逆透视为行:

select 
  Field,
  value, 
  Dt = case when rn = 1 then 'Today' else 'Yesterday' end
from
(
  select [Date], A, B, C, D,
    rn = row_number() over(order by [Date] desc) 
  from #yourtable
) x
cross apply
(
  values
  ('A', A),
  ('B', B),
  ('C', C),
  ('D', D)  -- include additional columns here if you have more
) c (Field, value)
where rn <= 2 -- return top 2 dates

在此,您会将列转换为行,然后仅return 具有您想要的前 2 个日期(今天和昨天)的行。最后,您将 TodayYesterday 值转换为列并计算您的百分比变化。所以把它们放在一起:

select 
  Field,
  Today, 
  Yesterday,
  ChangePercent = round((Today-Yesterday)/ Yesterday *100.0, 2)
from
(
  select 
    Field,
    value, 
    Dt = case when rn = 1 then 'Today' else 'Yesterday' end
  from
  (
    select [Date], A, B, C, D,
      rn = row_number() over(order by [Date] desc) 
    from #yourtable
  ) x
  cross apply
  (
    values
    ('A', A),
    ('B', B),
    ('C', C),
    ('D', D)
  ) c (Field, value)
  where rn <= 2 -- return top 2 dates
) d
pivot
(
  max(value)
  for dt in (Today, Yesterday)
) piv

这是一个demo。这给你结果:

Field Today Yesterday ChangePercent 
----- ----- --------- ------------- 
A     1.1   1         10            
B     2.1   2         5             
C     3.1   3         3.33          
D     4.1   4         2.5