【问题标题】:Merging rows to columns将行合并到列
【发布时间】:2015-09-03 21:38:38
【问题描述】:

我有以下情况(严重抽象,不良设计请忽略):

CREATE TABLE dbo.PersonTest (Id INT, name VARCHAR(255))

INSERT INTO dbo.PersonTest
        (Id, name )
VALUES  (1, 'Pete')
,       (1, 'Marie')
,       (2, 'Sam')
,       (2, 'Daisy')

我正在寻找以下结果:

Id  Name1   Name2
1   Marie   Pete
2   Daisy   Sam

因此,对于每个 Id,应该合并行。

得到这个结果我使用了以下查询:

WITH PersonRN AS
(
    SELECT  *
    ,       ROW_NUMBER() OVER(PARTITION BY Id ORDER BY name) RN
    FROM    dbo.PersonTest
)

SELECT      PT1.Id
,           PT1.name Name1
,           PT2.name Name2
FROM        PersonRN AS PT1
LEFT JOIN   PersonRN AS PT2 -- Left join in case there's only 1 name
        ON  PT2.Id = PT1.Id
        AND PT2.RN = 2
WHERE       PT1.RN = 1

效果很好。

我的问题是:这是最好的方法吗(在性能和弹性方面最好)?例如,如果其中一个 Id 有第三个名称,则我的查询将忽略该第三个名称。我认为最好的处理方法是动态 SQL,这很好,但如果它可以在没有动态的情况下完成,我会更喜欢。

【问题讨论】:

  • 更好的方法是PIVOT,如果您想将行更改为列,如果您事先知道最大名称自加入就足够了。
  • 你可以阅读my answer for inspiration和现场演示
  • @lad2025 感谢您的链接。我也一直在考虑PIVOT,但无法让它发挥作用。我以前没有使用过它,而且它不像我想要的那样直观。我想我得练习一些..
  • @HoneyBadger 我也在尝试PIVOT,但仍然没有成功

标签: sql sql-server


【解决方案1】:

除了动态PIVOT,您还可以使用Dynamic Crosstab 执行此操作,我更喜欢它的可读性。

SQL Fiddle

DECLARE @sql1 VARCHAR(1000) = '',
        @sql2 VARCHAR(1000) = '',
        @sql3 VARCHAR(1000) = ''
DECLARE @max INT

SELECT TOP 1 @max = COUNT(*) FROM PersonTest GROUP BY ID ORDER BY COUNT(*) DESC

SELECT @sql1 = 
'SELECT
    ID' + CHAR(10)

SELECT @sql2 = @sql2 +
'   , MAX(CASE WHEN RN =' + CONVERT(VARCHAR(5), RN) 
    + ' THEN name END) AS ' + QUOTENAME('Name' + CONVERT(VARCHAR(5), RN)) + CHAR(10)
FROM(
    SELECT TOP(@max)
        ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RN
    FROM sys.columns
)t
ORDER BY RN

SELECT @sql3 =
'FROM(
    SELECT *,
        RN = ROW_NUMBER() OVER(PARTITION BY ID ORDER BY name)
    FROM PersonTest
)t
GROUP BY ID
ORDER BY ID'

PRINT (@sql1 + @sql2 + @sql3)
EXEC (@sql1 + @sql2 + @sql3)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-02
    • 2022-11-23
    • 1970-01-01
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    • 2020-08-31
    • 2019-12-01
    相关资源
    最近更新 更多