【问题标题】:Performance of PIVOT and MERGE - is there a better way I can do this?PIVOT 和 MERGE 的性能 - 有没有更好的方法可以做到这一点?
【发布时间】:2015-11-08 23:26:10
【问题描述】:

抱歉,这可能有点超出社区的范围,但我想获得第二个意见。

我有一个结构如下的表

Table_1 
TYPE    ITEM    DATE        QTYA    QTYB    QTYC
X       AAA     17/08/2015  100     200     300 
X       AAA     18/08/2015  100     170     240 
Y       BBB     17/08/2015  100     240     100

我需要将此表用作合并的源,但目标表的格式完全不同

Table_2 
ITEM   QTYA_1   QTYA_2......QTYA_31 QTYB_1  QTYB_2  QTYB_3......QTYB_31 QTYC_1  QTYC_2....QTYC_31

(数字后缀基本上是一个月的某一天)

我可以混合使用 UNION ALL 和 PIVOT 将表 1 转换为表 2 的格式,但性能不是那么好 - 特别是因为我必须先将信息保存在临时表中,然后再将其合并到 ( Table_1 中的每个“类型”都有不同的开始日期,我不能从不同的日期开始覆盖 Table_2 中以前的值 - 基本上我必须将表与不同的项目类型和不同的开始日期合并 3 或 4 次)

这是我目前得到的结果

SELECT TOP 0 * INTO #TEMP_PIVOT_TABLE
INSERT INTO #TEMP_PIVOT_TABLE SELECT * FROM
    (SELECT ITEM, 'QTYA_' + CONVERT(DATETIMEFROMPARTS(day,DATE) AS VARCHAR) as 'Quantity Type', QTY_A FROM TABLE_1
        UNION_ALL
    SELECT ITEM, 'QTYB_' + CONVERT(DATETIMEFROMPARTS(day,DATE) AS VARCHAR) as 'Quantity Type', QTY_B FROM TABLE_1
        UNION_ALL
    SELECT ITEM, 'QTYC_' + CONVERT(DATETIMEFROMPARTS(day,DATE) AS VARCHAR) as 'Quantity Type', QTY_C FROM TABLE_1
    ) A
    PIVOT
    (SUM(QUANTITY) FOR QUANTITY_TYPE IN ([QTYA_1], [QTYA_2],.....[QTYA_31],[QTYB_1].....[QTYC_31],[QTYC_1].....[QTYC_31])) AS B

----For each different date per item_type, construct a string only selecting those days in the month.
Then merge the results from #TEMP_PIVOT_TABLE into TABLE_2 for each Item TYPE` with dynamic SQL

1) 有没有更好的方法来执行 PIVOT 命令? UNION ALL 命令的性能并不令人鼓舞——特别是因为我正在读取的表有大量数据。为了简洁起见,我在这里也进行了简化——实际的表需要映射 5 列左右,每列 31 天

2) 有没有更好的方法来进行 MERGE?我不喜欢使用循环 + 动态 SQL 基本上重复读取相同的数据集,以便在不同的列上合并,但我看不到不同的方式。这以及使用如此多的列动态构建 MERGE 命令将使其对未来的维护很麻烦。

有谁知道如何更有效地解决这个问题?

【问题讨论】:

    标签: sql-server merge pivot


    【解决方案1】:

    您可以将union all 内部查询替换为以下查询。这个查询只需要一个表命中,而不是每列都命中一个表。

    要取消透视数据,请使用 cross applytable valued constructor

    select ITEM,[Quantity Type],QTY 
    from yourtable 
    cross apply 
    (
    values 
    ('QTYA_' + CONVERT(DATEPART(day,DATE) AS VARCHAR),QTY_A),
    ('QTYB_' + CONVERT(DATEPART(day,DATE) AS VARCHAR),QTY_B),
    ('QTYC_' + CONVERT(DATEPART(day,DATE) AS VARCHAR),QTY_C),
    ) 
    CS ([Quantity Type],QTY)
    

    【讨论】:

    • 以前从未使用过[CROSS APPLY],现在将研究它,谢谢!对 MERGE 难题有什么建议吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 2011-03-10
    相关资源
    最近更新 更多