2015-04-14 3 views
0

Я имею таблицу ниже ...Rollup несколько значений в столбце, чтобы отделить столбцы

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, но я не уверен, что какая-нибудь помощь будет оценена.

ответ

0

Следующий сценарий даст вам результат, который вы хотите. Сначала устанавливается максимальное количество телефонных номеров для любого ID. Затем он строит строку со сводными столбцами, используя максимальное количество телефонных номеров (формы «[Телефон 1], ..., [Телефон N]», где N - это максимальное число). Наконец, динамический оператор SQL строится с использованием столбцов PIVOT, которые затем выполняются.

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 записи. –

Смежные вопросы