汇总列中的多个值以分隔列

时间:2015-04-14 19:44:01

标签: sql-server-2008

我有下表...

 ID     Phone     Address
 1        502      100 Main
 1        602      100 Main
 2        502      500 S Main
 3        444      201 N Point
 3        777      201 N Point
 4        111      999 South

我想看看......

 ID     Phone1     Phone2  Phone3   Address
 1       502         602            100 Main
 2       502                        500 S Main
 3       444        777             201 N Point
 4       111                        999 South  

我可以拥有超过2个手机号码,我认为可能是Pivot,但我不确定任何帮助是否值得赞赏。

2 个答案:

答案 0 :(得分:0)

If Object_Id('tempdb.dbo.#test') Is Not Null
Begin
    Drop Table #test;
End

If Object_Id('tempdb.dbo.#finalResult') Is Not Null
Begin
    Drop Table #finalResult;
End

If Object_Id('tempdb.dbo.#test') Is Null
Begin
    Create Table #test
    (
         RowId          Int Identity(1,1) Primary Key
        ,Id             Int
        ,Phone          Varchar(100)
        ,Address        Varchar(2000)
        ,PhoneUId       Int Default 0
    )
End

If Object_Id('tempdb.dbo.#finalResult') Is Null
Begin
    Create Table #finalResult
    (
        Id              Int Primary Key
    )
End


Declare  @MaxPhoneCount     Int
        ,@PhoneLoop         Int
        ,@SqlToRun          Varchar(5000)

Select  @SqlToRun = ''


Insert Into #test (Id,Phone,Address) Values
 (1,'502','100 Main')
,(1,'602','100 Main')
,(2,'502','500 S Main')
,(2,'622','500 S Main')
,(2,'782','500 S Main')
,(3,'444','201 N Point')
,(3,'777','201 N Point')
,(4,'111','999 South');


Update  t
Set     t.PhoneUId = t1.PhoneUid
From    #test As t
        Join
        (
            Select   t.RowId
                    ,ROW_NUMBER() Over(Partition By t.Id Order By t.Id) As PhoneUid
            From    #test As t With (Nolock)
        ) As t1 On t.RowId = t1.RowId


Select   @MaxPhoneCount = Max(tr.PhoneCount) 
        ,@PhoneLoop = 1
From    (
            Select   t.Id
                    ,Count(t.Phone) As PhoneCount
            From    #test As t With (Nolock)
            Group By t.Id
        ) As tr

Select  @SqlToRun = 'Alter Table #finalResult Add '
While (@PhoneLoop <= @MaxPhoneCount)
Begin
    Select  @SqlToRun = @SqlToRun + (Case When @PhoneLoop > 1 Then ',' Else '' End) + ' Phone' + Cast(@PhoneLoop As Varchar(100)) + ' Varchar(100)'

    Select  @PhoneLoop = @PhoneLoop + 1
End
Select  @SqlToRun = @SqlToRun + ',' + ' Address Varchar(2000)'

----Print (@SqlToRun)
Exec (@SqlToRun)


Insert Into #finalResult(Id,Address)
Select  Distinct
         t.Id
        ,t.Address
From    #test As t With (Nolock)


Select   @SqlToRun = ''
        ,@PhoneLoop = 1

While (@PhoneLoop <= @MaxPhoneCount)
Begin
    Select  @SqlToRun = 'Update fr Set fr.Phone' + Cast(@PhoneLoop As Varchar(20)) + ' = t.Phone From #finalResult As fr With (Nolock) ' +
            'Join #test As t With (Nolock) On fr.Id = t.Id  Where t.PhoneUId =' + Cast(@PhoneLoop As Varchar(20)) + ';'

    ----Print (@SqlToRun)
    Exec (@SqlToRun)

    Select   @PhoneLoop = @PhoneLoop + 1
            ,@SqlToRun = ''
End


Select  *
From    #finalResult As fr With (Nolock)

答案 1 :(得分:0)

以下脚本会为您提供所需的结果。它首先确定任何ID的最大电话号码数。然后使用最大数量的电话号码(形式为'[Phone 1],...,[Phone N]',其中N为最大数量)构建带有枢轴列的字符串。最后,使用PIVOT列构建动态SQL语句,然后执行该语句。

CREATE TABLE #t(
    ID INT,
    Phone INT,
    [Address] VARCHAR(256)
);

INSERT INTO #t
    (ID,Phone,[Address])
VALUES
    (1,502,'100 Main'),
    (1,602,'100 Main'),
    (2,502,'500 S Main'),
    (3,444,'201 N Point'),
    (3,777,'201 N Point'),
    (4,111,'999 South');

DECLARE @MaxPhoneCount INT;
SELECT 
    @MaxPhoneCount=MAX(pc.PhoneCount)
FROM
    (
        SELECT
            ID,
            COUNT(*) AS PhoneCount
        FROM
            #t
        GROUP BY
            ID
    ) AS pc;

DECLARE @PhoneIDS VARCHAR(8000);
DECLARE @i INT=1;
WHILE @i<=@MaxPhoneCount
BEGIN
    SET @PhoneIDS=
        CASE WHEN @PhoneIDS IS NULL 
            THEN '[Phone '+CAST(@i AS VARCHAR(2))+']'
            ELSE @PhoneIDS+',[Phone '+CAST(@i AS VARCHAR(2))+']'
        END;
    SET @i=@i+1;
END

DECLARE @sql VARCHAR(MAX);
SET @sql='
    SELECT
        *
    FROM
        (
            SELECT
                ID,
                Phone,
                ''Phone '' + CAST(ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Phone) AS VARCHAR(2)) AS PhoneLabel,
                [Address]
            FROM
                #t
        ) AS p
        PIVOT(
            MAX(Phone)
            FOR PhoneLabel IN ('+@PhoneIDS+')
        ) AS piv
    ORDER BY
        ID';

EXEC (@sql);

DROP TABLE #t;

此脚本的结果是:

ID  Address     Phone 1 Phone 2
1   100 Main    502     602
2   500 S Main  502     NULL
3   201 N Point 444     777
4   999 South   111     NULL