2010-07-13 6 views
10

Besoin d 'aide à la clause de pivot dans SQL Server 2008. J'ai une table avec cette info:SQL Pivot avec plusieurs colonnes

 
Weekno DayOfWeek  FromTime ToTime 
1   2    10:00  14:00 
1   3    10:00  14:00 
2   3    08:00  13:00 
2   4    09:00  13:00 
2   5    14:00  22:00 
3   1    06:00  13:00 
3   4    06:00  13:00 
3   5    14:00  22:00 

Je veux convertir en une table qui ressemble à ceci:

 
Week Start1 End1 Start2 End2 Start3 End3 Start4 End4 Start5 End5 Start6 End6 Start7 End7 
1       10:00  14:00 10:00  14:00 
2           08:00  13:00 09:00  13:00 14:00  22:00 
3  06:00  13:00          06:00  13:00 14:00  22:00 

Y a-t-il un moyen de faire avec une requête pivot? S'il vous plaît écrivez répondre avec un exemple sur la façon de le faire.

J'apprécie toute sorte d'aide à ce sujet. Merci d'avance.

+0

duplication possible de [Pivot de plusieurs colonnes dans T-SQL] (http://stackoverflow.com/questions/947281/multiple-column-pivot-in-t-sql) –

Répondre

8

Personnellement, je déteste les pivots - difficile à lire et sans faille.

CREATE TABLE #test 
(
    WeekNo int, 
    [DayOfWeek] int, 
    FromTime time, 
    ToTime time 
    ) 

INSERT INTO #test 
SELECT 1,2,'10:00','14:00' 
UNION ALL 
SELECT 1,3,'10:00','14:00' 
UNION ALL 
SELECT 2,3,'08:00','13:00' 
UNION ALL 
SELECT 2,4,'09:00','13:00' 
UNION ALL 
SELECT 2,5,'14:00','22:00' 
UNION ALL 
SELECT 3,1,'06:00','13:00' 
UNION ALL 
SELECT 3,4,'06:00','13:00' 
UNION ALL 
SELECT 3,5,'14:00','22:00' 

SELECT WeekNo, 
    MAX(CASE WHEN DayOfWeek = 1 THEN FromTime ELSE NULL END) AS Start1, 
    MAX(CASE WHEN DayOfWeek = 1 THEN ToTime ELSE NULL END) AS End1, 
    MAX(CASE WHEN DayOfWeek = 2 THEN FromTime ELSE NULL END) AS Start2, 
    MAX(CASE WHEN DayOfWeek = 2 THEN ToTime ELSE NULL END) AS End2, 
    MAX(CASE WHEN DayOfWeek = 3 THEN FromTime ELSE NULL END) AS Start3, 
    MAX(CASE WHEN DayOfWeek = 3 THEN ToTime ELSE NULL END) AS End3, 
    MAX(CASE WHEN DayOfWeek = 4 THEN FromTime ELSE NULL END) AS Start4, 
    MAX(CASE WHEN DayOfWeek = 4 THEN ToTime ELSE NULL END) AS End4, 
    MAX(CASE WHEN DayOfWeek = 5 THEN FromTime ELSE NULL END) AS Start5, 
    MAX(CASE WHEN DayOfWeek = 5 THEN ToTime ELSE NULL END) AS End5, 
    MAX(CASE WHEN DayOfWeek = 6 THEN FromTime ELSE NULL END) AS Start6, 
    MAX(CASE WHEN DayOfWeek = 6 THEN ToTime ELSE NULL END) AS End6, 
    MAX(CASE WHEN DayOfWeek = 7 THEN FromTime ELSE NULL END) AS Start7, 
    MAX(CASE WHEN DayOfWeek = 7 THEN ToTime ELSE NULL END) AS End7 
    FROM #test 
    GROUP BY WeekNo 

Et ça va souffler les chaussettes d'un pivot; performance sage.

+0

On dirait un tirage entre les deux approches performances sage. –

+0

@ Martin Smith - Le mien doit UNPIVOT premier. À cause de cela, j'aurais pensé que le «pivot» traditionnel aurait été plus rapide. –

+0

Impossible de dire réellement en fonction de cet ensemble de données; aurait besoin de créer de grandes données de test. Même avec ces minuscules données, l'onglet croisé fonctionne mieux (0ms vs 6ms). Mais vérifiez les plans d'exécution si vous êtes intéressé par les différences. –

15

est ici la version pivot:

https://data.stackexchange.com/stackoverflow/query/7295/so3241450

-- SO3241450 

CREATE TABLE #SO3241450 (
    Weekno int NOT NULL 
    ,DayOfWeek int NOT NULL 
    ,FromTime time NOT NULL 
    ,ToTime time NOT NULL 
) 

INSERT INTO #SO3241450 VALUES 
(1, 2, '10:00', '14:00') 
,(1, 3, '10:00', '14:00') 
,(2, 3, '08:00', '13:00') 
,(2, 4, '09:00', '13:00') 
,(2, 5, '14:00', '22:00') 
,(3, 1, '06:00', '13:00') 
,(3, 4, '06:00', '13:00') 
,(3, 5, '14:00', '22:00') 

;WITH Base AS (
    SELECT Weekno, DayOfWeek, FromTime AS [Start], ToTime AS [End] 
    FROM #SO3241450 
) 
,norm AS (
SELECT Weekno, ColName + CONVERT(varchar, DayOfWeek) AS ColName, ColValue 
FROM Base 
UNPIVOT (ColValue FOR ColName IN ([Start], [End])) AS pvt 
) 
SELECT * 
FROM norm 
PIVOT (MIN(ColValue) FOR ColName IN ([Start1], [End1], [Start2], [End2], [Start3], [End3], [Start4], [End4], [Start5], [End5], [Start6], [End6], [Start7], [End7])) AS pvt​ 
+0

+1 pour montrer la version pivotante –

+1

Absolument génial! Je peux maintenant pivoter et afficher autant de colonnes que je veux. Je vous remercie! Je voudrais mettre en garde ceci en disant que pendant le processus UnPivot (avant Pivoter à la fin) toutes les colonnes sont jetées dans une seule colonne. C'est très bien pour cet exemple, mais si vous mélangez des nombres, des dates et des chaînes, je suggère de tout lancer comme un VarChar pour éviter les erreurs (et ensuite retourner à leurs types de données d'origine si nécessaire). – MikeTeeVee

0

Je pense que le cas où ne fonctionnera que s'il n'y a que Weekno unique et DAYOFWEEK car il ne renvoie des enregistrements de dernière heure de début et de fin et filtrer le reste. Exemple

Weekno DayOfWeek  FromTime ToTime 
1   2    10:00  14:00 
1   2    07:00  09:00 
2   3    08:00  13:00 
2   4    09:00  13:00 

Il ne retourne que la première rangée de weekno 1 de DAYOFWEEK 2 et ignorer la deuxième rangée.