【问题标题】:How to convert multiple row data to multiple column using PIVOT in SQL-SERVER?如何在 SQL-SERVER 中使用 PIVOT 将多行数据转换为多列?
【发布时间】:2018-02-06 18:24:30
【问题描述】:

我正在寻找一种使用 Pivot 将 SQL Server 中的行转换为列的有效方法。我已经使用带有案例和连接的聚合函数分别获得了输出,但我希望 PIVOT 是一种处理这种行到列转换的清晰方法。

示例数据是

-------------------------------------
| ID | Row | First |Last | Postal |
------------------------------------
| 1  | 1   | John  | Doe | B4K    |
| 1  | 2   | Matt  | Kev | 2H1    |
| 2  | 1   | Hary  | Lot | L26    |
| 2  | 2   | Fork  | Har | M3R    |
| 3  | 1   | Yuv   | Hal | L39    |
------------------------------------

这是我的结果:

| ID | First1 |Last1 | Postal1 | First2 |Last2 | Postal2 |
 -----------------------------------------------------------
| 1  | John   | Doe  | B4K     | Matt   | Kev  | 2H1     |
| 2  | Hary   | Lot  | L26     | Fork   | Har  | M3R     |
| 3  | Yuv    | Hal  | L39     | NULL   | NULL | NULL    |
-----------------------------------------------------------

如何使用 PIVOT 实现此结果?

【问题讨论】:

  • 更改聚合函数以获得预期结果。你不需要Pivot
  • 如果您不知道需要将多少行转换为列(在您的情况下为 2、2、1),pivot 无法帮助您。您应该构建动态枢轴,这将是复杂的查询
  • 我知道每个 ID 的最大限制。所以,在这种情况下,@Denis UnPivot/Pivot 应该仍然可以工作。

标签: sql sql-server pivot


【解决方案1】:

您的数据:

CREATE TABLE #Test (
    ID          INT,
    [Row]       INT,
    [First]     VARCHAR(32),
    [Last]      VARCHAR(32),
    [Postal]    VARCHAR(32)
)

INSERT #Test
VALUES
(1, 1, 'John', 'Doe', 'B4K'),
(1, 2, 'Matt', 'Kev', '2H1'),
(2, 1, 'Hary', 'Lot', 'L26'),
(2, 2, 'Fork', 'Har', 'M3R'),
(3, 1, 'Yuv', 'Hal', 'L39')

要获得预期的结果,您必须在使用 PIVOT 之前使用 UNPIVOT,如下所示:

SELECT *
FROM (
    SELECT ID, ITEM + CAST([Row] AS VARCHAR) AS Name, VALUE
    FROM (
        SELECT *
        FROM #Test
    )s
    UNPIVOT
    (VALUE FOR Item IN ([First], [Last], [Postal])) p
) src
PIVOT
(MAX(VALUE) FOR Name IN ([First1], [Last1], [Postal1], [First2], [Last2], [Postal2])
) pvt

显然,(MAX(VALUE) FOR Name IN ([First1], [Last1], [Postal1], [First2], [Last2], [Postal2]) 行取决于字段 [Row] 中不同值的计数,因此必须动态创建查询。

您可以动态创建将使用OUTER APPLY 的查询,而不是使用UNPIVOT/PIVOT

SELECT DISTINCT ID,
    t1.[First]  AS First1,
    t1.[Last]   AS Last1,
    t1.Postal   AS Postal1,
    t2.[First]  AS First2,
    t2.[Last]   AS Last2,
    t2.Postal   AS Postal2
FROM #Test t

    OUTER APPLY (
        SELECT TOP 1 [First], [Last], [Postal]
        FROM #Test
        WHERE ID = t.ID
            AND [Row] = 1
        ) t1

    OUTER APPLY (
        SELECT TOP 1 [First], [Last], [Postal]
        FROM #Test
        WHERE ID = t.ID
            AND [Row] = 2
        ) t2

【讨论】:

  • 感谢您从不同的角度解决这个问题。您知道 Pivot 是否优于 Aggregate 方法吗?
  • 我认为没有人能告诉你在不了解索引和表大小的情况下哪个更有效。您应该分析这两个查询的执行计划,然后选择合适的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-25
  • 2013-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多