2015-04-14 28 views
0

我有下面的表...汇总多个值单独列

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#电话每个身份证,我想可能是枢轴,但我不知道任何帮助将是赞赏。

回答

0

以下脚本会给你你想要的结果。它首先为任何ID建立最大数量的电话号码。然后它使用最大数量的电话号码(形式为'[电话1],...,[电话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<[email protected] 
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 @[email protected]+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 ('[email protected]+') 
     ) 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 
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) 
+0

上面的代码将用于N个电话的运行,但是性能可能下降时数据超过1,00,000记录。 –