2012-03-17 2 views
0

J'ai besoin de transformer plusieurs enregistrements similaires en un seul enregistrement. Il peut y avoir jusqu'à 10 lignes à combiner. Chaque groupe de lignes à combiner a le même ID. Et les valeurs des données de ligne ne sont pas pertinentes (seront en fait un GUID). données ressemble à ceci:Transformer des données de plusieurs enregistrements en un seul enregistrement sur un serveur SQL

Tableau 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 

je besoin de transformer cette structure et ont seulement un enregistrement par ID. Il peut y avoir N nombre de colonnes basé sur le nombre d'enregistrements qui ont le même ID (environ 10).

Tableau 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 

Je ne peux pas modifier le tableau B du tout. Juste fusionner ou insérer dedans.
J'utilise SQL Server 2008 R2 et le volume de la table A est d'environ un million d'enregistrements.
Toute aide est grandement appréciée.

MISE À JOUR: Ajout de vraies définitions de tables.

Voici le TableA créer le script:

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 

Voici le script pour créer TableB: SET ANSI_NULLS SUR 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 

Répondre

3

Vous pouvez essayer avec unpivot/pivot combinaison. Unpivot transforme TableA en rangées de trois colonnes seulement, id, ColumnID et guid, par exemple

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

ajoutant numéro unique à chaque combinaison identifiant/colonne (row_number sur (...) partiel), et le fait que, pour chaque rangée dans la TableA. Pivot va les transformer en une seule rangée par 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 

Ne soyez pas alarmé par la présence de min (guid). C'est ici parce que le pivot insiste sur la fonction d'agrégat. Comme il n'y a qu'un guid par combinaison ID/ColumnID, il n'y aura pas de valeurs manquantes. Pour vérifier, remplacer min (guid) par count (guid) et vérifier les valeurs supérieures à 1.

MISE À JOUR: pour éviter de mélanger des lignes différentes à partir du même ID, j'ai dû changer l'ordre par clause de row_number() à la commande par primary clé de TableA. Si la table n'a pas PK, il faut transformer l'entrée de sorte qu'il comprend row_number() comme clé primaire de substitution:

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

et utiliser la table dérivée au lieu de table d'origine.

MISE À JOUR 2:

Mon erreur a été de placer row_number() dans UNPIVOT sélectionnez. Les numéros de ligne pour ID doivent être récupérés avant la transformation, évidemment.Ceci est un pivot qui utilise des tables originales:

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

Merci pour l'idée Nikola, mais j'ai l'erreur suivante: Le type de données opérande uniqueidentifier n'est pas valide pour l'opérateur min. – sreeli

+0

Essayez de le convertir en varchar avant de le faire pivoter. –

+0

@sreeli - avez-vous essayé de convertir guid en varchar pendant le non pivotement et de le convertir en guid après pivotement? –

Questions connexes