You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用UNPIVOT/CROSS APPLY替代UNION ALL实现两年数据对比?

批量指标年度对比查询的优化实现

现有表结构与数据

临时表#CarPartSales存储汽车配件销售数据,结构及初始化代码如下:

CREATE TABLE #CarPartSales (
        Make        VARCHAR(100)
,       Model       VARCHAR(100)
,       Part        VARCHAR(100)
,       Color       VARCHAR(100)
,       SalesYear   INT
,       TotalSold   DECIMAL(18,2)
,       Invoices    DECIMAL(18,2)
,       TotalPrice  DECIMAL(18,2)
)

INSERT INTO #CarPartSales VALUES 
    ('Chevy','Nova','Door','Red',2023, 120.00, 100.00, 900.50)
,   ('Chevy','Nova','Door','Red',2022, 100.00, 90.00, 850.25)
,   ('Chevy','Nova','Door','Black',2023, 70.00, 50.00, 450.75)
,   ('Chevy','Nova','Door','Black',2022, 20.00, 8.00, 200.00)
,   ('Ford','Fairlaine','Hood','White',2023, 100.00, 75.00, 780.35)
,   ('Ford','Fairlaine','Hood','White',2022, 70.00, 65.00, 650.20)
,   ('Dodge','Aspen','Fender','Green',2023, 30.00, 10.00, 125.00)
,   ('Dodge','Aspen','Fender','Green',2022, 10.00, 3.00, 75.55)

需求与原始实现

需要生成包含Make、Model、Part、Color、指标类别、2022年数值、2023年数值及差值的结果集。

最初采用多次UNION ALL实现,代码如下:

SELECT      Make
,           Model
,           Part
,           Color
,           Category        = 'TotalSold'
,           PreviousValue   = SUM(CASE WHEN SalesYear = 2022 THEN TotalSold END)
,           CurrentValue    = SUM(CASE WHEN SalesYear = 2023 THEN TotalSold END)
,           ValueChange     = SUM(CASE WHEN SalesYear = 2023 THEN TotalSold END) - SUM(CASE WHEN SalesYear = 2022 THEN TotalSold END)
FROM        #CarPartSales
GROUP BY    Make
,           Model
,           Part
,           Color

UNION ALL

SELECT      Make
,           Model
,           Part
,           Color
,           Category        = 'Invoices'
,           PreviousValue   = SUM(CASE WHEN SalesYear = 2022 THEN Invoices END)
,           CurrentValue    = SUM(CASE WHEN SalesYear = 2023 THEN Invoices END)
,           ValueChange     = SUM(CASE WHEN SalesYear = 2023 THEN Invoices END) - SUM(CASE WHEN SalesYear = 2022 THEN Invoices END)
FROM        #CarPartSales
GROUP BY    Make
,           Model
,           Part
,           Color

UNION ALL

SELECT      Make
,           Model
,           Part
,           Color
,           Category        = 'TotalPrice'
,           PreviousValue   = SUM(CASE WHEN SalesYear = 2022 THEN TotalPrice END)
,           CurrentValue    = SUM(CASE WHEN SalesYear = 2023 THEN TotalPrice END)
,           ValueChange     = SUM(CASE WHEN SalesYear = 2023 THEN TotalPrice END) - SUM(CASE WHEN SalesYear = 2022 THEN TotalPrice END)
FROM        #CarPartSales
GROUP BY    Make
,           Model
,           Part
,           Color

ORDER BY 1,2,3,4,5

但实际场景中有50余个指标类别,重复编写UNION ALL的方式过于繁琐,因此希望通过UNPIVOT或CROSS APPLY简化实现。

优化后的实现(CTE + UNPIVOT)

通过CTE结合UNPIVOT将多列指标转置为行,再统一聚合计算,大幅减少重复代码,实现如下:

;WITH cte AS (
SELECT      SalesYear, Make, Model, Part, Color, ColumnName, value
FROM        (
    SELECT      SalesYear, Make, Model, Part, Color, TotalSold, Invoices, TotalPrice
    FROM        #CarPartSales
            ) AS SourceTable
UNPIVOT     (   
                value FOR ColumnName IN (
                        TotalSold
                ,       Invoices
                ,       TotalPrice)
            ) as Alias
)
SELECT      Make
,           Model
,           Part
,           Color
,           ColumnName
,           CurrentValue  = SUM(CASE WHEN SalesYear = 2023 THEN value END)
,           PreviousValue = SUM(CASE WHEN SalesYear = 2022 THEN value END)
,           ValueChange   = SUM(CASE WHEN SalesYear = 2023 THEN value END) - SUM(CASE WHEN SalesYear = 2022 THEN value END)
FROM        cte
GROUP BY    Make
,           Model
,           Part
,           Color
,           ColumnName
ORDER BY    1,2,3,4,5

后续新增指标时,仅需在UNPIVOT的IN列表中添加对应列名即可,无需重复编写聚合逻辑。

内容的提问来源于stack exchange,提问作者Jeff Brady

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 09:44:53