Transposer une table dans le server SQL

J'utilise SQL Server 2005 pour mon application. J'ai une table dans ma procédure stockée qui a deux colonnes, C1 et C2. Je veux transposer cette table de telle sorte que les valeurs de la colonne C1 deviennent les colonnes. Avant la transposition (Tableau 1):

C1 C2 M1 U1 M1 U2 M1 U3 M2 U4 M2 U5 

Après la transposition (tableau 2):

 M1 M2 U1 U4 U2 U5 U3 NULL 

Dans le tableau 1, le nombre de valeurs distinctes (M1, M2) peut varier. Ainsi, les colonnes du tableau 2 ne sont pas corrigées.

S'il vous plaît fournir une solution pour atteindre le même.

Pour ce type de transformation de données, vous souhaiterez utiliser la fonction PIVOT disponible dans SQL Server 2005+. Il existe deux façons d'appliquer la fonction de pivot .

Si vous connaissez les valeurs à l'avance, vous pouvez coder en dur les valeurs dans la requête. Similaire à ceci:

 select M1, M2 from ( select c1, c2, row_number() over(partition by c1 order by c1, c2) rn from yourtable ) src pivot ( max(c2) for c1 in (M1, M2) ) piv 

Voir SQL Fiddle avec démo .

Mais si vous avez un nombre inconnu de valeurs que vous souhaitez transposer en colonnes, vous pouvez utiliser SQL dynamic pour créer la requête au moment de l'exécution.

 DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX) select @cols = STUFF((SELECT distinct ',' + QUOTENAME(C1) from yourtable FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'') set @query = 'SELECT ' + @cols + ' from ( select C1, C2, row_number() over(partition by c1 order by c1, c2) rn from yourtable ) x pivot ( max(C2) for C1 in (' + @cols + ') ) p ' execute(@query) 

Voir SQL Fiddle avec démo .

Les deux donneront le même résultat, la différence est que la version dynamic est flexible si les valeurs changent:

 | M1 | M2 | --------------- | U1 | U4 | | U2 | U5 | | U3 | (null) | 

C'est probablement un cas où SQL dynamic est votre ami. En supposant que le nom de votre table de base est "Transposer":

 --Get a Unique List of values from C1 --> These will be our column headers DECLARE @Unique TABLE (C1 VARCHAR(25), fUsed BIT DEFAULT 0); INSERT INTO @Unique (C1) SELECT DISTINCT C1 FROM Transpose; DECLARE @TransSQL NVARCHAR(4000); DECLARE @ColID NVARCHAR(25); SET @TransSQL = N'SELECT ' --Loop over unique C1 values and construct the select statement SELECT @ColID = (SELECT TOP 1 C1 FROM @Unique WHERE fUSed = 0); WHILE @@ROWCOUNT <> 0 AND @ColID IS NOT NULL BEGIN SET @TransSQL = @TransSQL + 'CASE C1 WHEN ' + '''' + @ColID + '''' + ' THEN C2 ELSE NULL END AS ' + @ColID + ', ' --Update flag in table so we don't use this field again UPDATE u SET fUsed = 1 FROM @Unique u WHERE C1 = @ColID; SELECT @ColID = (SELECT TOP 1 C1 FROM @Unique WHERE fUSed = 0); END --Remove Trailing comma and add FROM clause DECLARE @SQL NVARCHAR(4000) SET @SQL = LEFT(@TransSQL,LEN(@TransSQL) -1) + ' FROM Transpose' --For debugging purposes PRINT @SQL; --Execute the dynamic sql EXEC sp_executesql @SQL; 

Cela ne permettra pas d'get la layout exacte de votre question car il ne s'agit pas d'un champ key pour regrouper les résultats. Au lieu de cela, la sortie ressemblera à ceci:

 M1 M2 M3 U1 NULL NULL U2 NULL NULL U3 NULL NULL NULL U4 NULL NULL U5 NULL NULL NULL U6 

Si votre table de base comporte un champ key, la requête peut être légèrement modifiée pour regrouper les résultats par champ key et vous rapprocher un peu plus de votre objective déclaré pour datatables résultantes.

Ce n'est pas le résultat exact que vous voulez mais vous pouvez essayer ceci

 ;WITH TAB1 AS ( SELECT [ResponsibleID] C1,[ActionID] C2,1 ORD FROM [TEST].[dbo].[yourtable] WHERE 1=1 ) SELECT CASE WHEN M1=1 THEN ActionID ELSE NULL END M1, CASE WHEN M2=1 THEN ActionID ELSE NULL END M2 FROM TAB1 PIVOT(AVG(ORD) FOR RESPONSIBLEID IN ([M1],[M2])) AS ABC