2012-03-17 87 views
0

我需要將多個相似記錄轉換爲單個記錄。 最多可以有10行需要組合。 需要組合的每組行都具有相同的ID。行數據的值是不相關的(實際上將是一個GUID)。 數據看起來是這樣的:在sql server中將數據從多個記錄轉換爲單個記錄

表A

ID C1 C2 C3 
ID1 x x  x 
ID1 y y  y 
ID2 y y  y 
ID2 x x  x 
ID2 y y  y 
ID2 y y  y 
ID3 x x  x 
ID3 y y  y 
ID3 y y  y 

我需要轉換到這個結構,只有每個ID只能有一個記錄。根據具有相同ID(約10)的記錄數可以有N列。

表B

ID  C1  C2  C3  C1A  C2A  C3A  C1B  C2B  C3B 
ID1 x  x  x  y  y  y  null null null 
ID2 y  y  y  x  x  x  y  y  y 
ID3 x  x  x  y  y  y  y  y  y 

我不能修改表B中的。只需合併或插入它。
我正在使用SQL Server 2008 R2,表A的卷大約有一百萬條記錄。
任何幫助大大appriciated。

更新:添加真實的表格定義。

這裏是表A創建腳本:

SET ANSI_NULLS ON 
    GO 

SET QUOTED_IDENTIFIER ON 
GO 

CREATE TABLE [dbo].[IntervalPivotTable](
    [UID] [uniqueidentifier] NOT NULL, 
    [ServiceHash] [int] NULL, 
    [IntervalID] [nvarchar](50) NULL, 
    [IntervalTypeID] [nvarchar](50) NULL, 
    [IntervalGroupID] [nvarchar](50) NULL, 
    [DrivingConditionID] [nvarchar](50) NULL, 
CONSTRAINT [PK_IntervalPivotTable] PRIMARY KEY CLUSTERED 
(
    [UID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS =  ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[IntervalPivotTable] ADD CONSTRAINT [DF_IntervalPivotTable_UID] DEFAULT   (newid()) FOR [UID] 
GO 

下面是表B創建腳本: SET ANSI_NULLS ON GO

SET QUOTED_IDENTIFIER ON 
GO 

CREATE TABLE [dbo].[PivotedIntervals](
    [ServiceHash] [int] NULL, 
    [IntervalID_0] [nvarchar](50) NULL, 
    [IntervalTypeID_0] [nvarchar](50) NULL, 
    [IntervalGroupID_0] [nvarchar](50) NULL, 
    [DrivingConditionID_0] [nvarchar](50) NULL, 
    [IntervalID_1] [nvarchar](50) NULL, 
    [IntervalTypeID_1] [nvarchar](50) NULL, 
    [IntervalGroupID_1] [nvarchar](50) NULL, 
    [DrivingConditionID_1] [nvarchar](50) NULL, 
    [IntervalID_2] [nvarchar](50) NULL, 
    [IntervalTypeID_2] [nvarchar](50) NULL, 
    [IntervalGroupID_2] [nvarchar](50) NULL, 
    [DrivingConditionID_2] [nvarchar](50) NULL, 
    [IntervalID_3] [nvarchar](50) NULL, 
    [IntervalTypeID_3] [nvarchar](50) NULL, 
    [IntervalGroupID_3] [nvarchar](50) NULL, 
    [DrivingConditionID_3] [nvarchar](50) NULL, 
    [IntervalID_4] [nvarchar](50) NULL, 
    [IntervalTypeID_4] [nvarchar](50) NULL, 
    [IntervalGroupID_4] [nvarchar](50) NULL, 
    [DrivingConditionID_4] [nvarchar](50) NULL, 
    [IntervalID_5] [nvarchar](50) NULL, 
    [IntervalTypeID_5] [nvarchar](50) NULL, 
    [IntervalGroupID_5] [nvarchar](50) NULL, 
    [DrivingConditionID_5] [nvarchar](50) NULL, 
    [IntervalID_6] [nvarchar](50) NULL, 
    [IntervalTypeID_6] [nvarchar](50) NULL, 
    [IntervalGroupID_6] [nvarchar](50) NULL, 
    [DrivingConditionID_6] [nvarchar](50) NULL, 
    [IntervalID_7] [nvarchar](50) NULL, 
    [IntervalTypeID_7] [nvarchar](50) NULL, 
    [IntervalGroupID_7] [nvarchar](50) NULL, 
    [DrivingConditionID_7] [nvarchar](50) NULL, 
    [IntervalID_8] [nvarchar](50) NULL, 
    [IntervalTypeID_8] [nvarchar](50) NULL, 
    [IntervalGroupID_8] [nvarchar](50) NULL, 
    [DrivingConditionID_8] [nvarchar](50) NULL, 
    [IntervalID_9] [nvarchar](50) NULL, 
    [IntervalTypeID_9] [nvarchar](50) NULL, 
    [IntervalGroupID_9] [nvarchar](50) NULL, 
    [DrivingConditionID_9] [nvarchar](50) NULL, 
    [IntervalID_10] [nvarchar](50) NULL, 
    [IntervalTypeID_10] [nvarchar](50) NULL, 
    [IntervalGroupID_10] [nvarchar](50) NULL, 
    [DrivingConditionID_10] [nvarchar](50) NULL 
) ON [PRIMARY] 

GO 

回答

3

你可能想嘗試unpivot/pivot組合。逆透視變換表A與三列只,ID,ColumnID的和GUID行,例如

ID1, C1_0, x 
ID1, C2_0, x 
ID1, C3_0, x 
ID1, C1_1, x 
ID1, C2_1, x 
ID1, C3_1, x 

添加唯一的號碼以每個ID /列組合(ROW_NUMBER超過(...)的一部分),並執行對於每個在TableA中排。樞軸將它們轉換成單排通過ID:

select * 
from 
(
    select id, 
     code 
     + '_' 
     + convert(varchar(10), ColumnID) - 1 ColumnID, 
     guid 
    from 
    (
    select TableA.*, 
      row_number() over (partition by ID 
           order by TableA_PK) - 1 ColumnID 
     from TableA 
) 
    unpivot 
    (
    guid for code in (c1, c2, c3) 
) as u 
) UnpivotedTable 
pivot 
(
    min(guid) 
    for columnid in ([c1_0], [c2_0], [c3_0], [c1_1], [c2_1], [c3_1]) 
) PivotedTable 

不要分鐘(GUID)的存在感到震驚。這是因爲樞軸堅持聚合函數。由於每個ID/ColumnID組合只有一個GUID,因此不會有缺失值。要驗證,用count(guid)替換min(guid)並檢查大於1的值。

UPDATE:爲避免混合來自同一ID的不同行,我必須更改row_number()表A的關鍵。如果表中沒有PK,應變換的輸入,以使其包括ROW_NUMBER()作爲一個代理主鍵:

(
     select TableA.*, row_number() over (order by ID) TableA_PK 
     from TableA 
) TableAWithAPrimaryKey 

和使用,而不是原來的表派生表。

更新2:

我的錯誤是在放置unpivot的選擇ROW_NUMBER()。顯然,在轉換之前必須提取ID的行號。這是一個使用原始表的關鍵點:

select * 
from 
(
    select ServiceHash, 
     code 
     + '_' 
     + convert(varchar(10), ColumnID) ColumnID, 
     guid 
    from 
    (
    select IntervalPivotTable.*, 
      row_number() over (partition by ServiceHash 
          order by UID) - 1 ColumnID 
     from IntervalPivotTable 
) a 
    unpivot 
    (
    guid for code in 
    (
     IntervalID, 
     IntervalTypeID, 
     IntervalGroupID, 
     DrivingConditionID 
    ) 
) as u 
) UnpivotedTable 
pivot 
(
    min(guid) 
    for columnid in 
    (
    IntervalID_0, 
    IntervalTypeID_0, 
    IntervalGroupID_0, 
    DrivingConditionID_0, 
    IntervalID_1, 
    IntervalTypeID_1, 
    IntervalGroupID_1, 
    DrivingConditionID_1, 
    IntervalID_2, 
    IntervalTypeID_2, 
    IntervalGroupID_2, 
    DrivingConditionID_2 
-- Continue list of pivoted columns up to _10 here 
) 
) PivotedTable 
+0

感謝尼古拉的想法,但我得到了以下錯誤:操作數數據類型uniqueidentifier對於最小操作符無效。 – sreeli 2012-03-18 02:33:42

+0

嘗試在旋轉之前將其轉換爲varchar。 – 2012-03-18 02:47:50

+0

@sreeli - 您是否嘗試在轉換過程中將guid轉換爲varchar,並在轉換後將其轉換回guid? – 2012-03-18 19:44:04

相關問題