2010-07-13 17 views
10

bisogno di aiuto con la clausola pivot in sql server 2008. Ho una tabella con queste informazioni:pivot SQL con più colonne

 
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 

voglio convertire questo in una tabella che assomiglia a questo:

 
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 

C'è un modo per fare una query pivot? Si prega di rispondere con un esempio su come farlo.

Apprezzo qualsiasi tipo di aiuto su questo. Grazie in anticipo.

+0

possibile duplicato di [Piper multiplo di colonna in T-SQL] (http://stackoverflow.com/questions/947281/multiple-column-pivot-in-t-sql) –

risposta

8

Personalmente odio i perni: difficile da leggere e disordinatamente.

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 

E farà saltare le calze da un perno; prestazioni saggio.

+0

Sembra un pareggio tra i due approcci prestazioni saggio. –

+0

@ Martin Smith - Il mio deve prima UNPIVOT. Per questo motivo, avrei pensato che il tradizionale "pivot" sarebbe stato più veloce. –

+0

Impossibile dire in base a questo set di dati; avrebbe bisogno di creare alcuni dati di test di grandi dimensioni. Anche con questi dati minuscoli il cross tab ha un rendimento migliore (0 ms vs 6 ms). Ma controlla i piani di esecuzione se sei interessato alle differenze. –

15

Ecco la versione 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 per mostrare la versione pivot –

+1

Absolutely Brilliant! Ora posso ruotare e visualizzare tutte le colonne che voglio. Grazie! Vorrei sottolineare questo dicendo che durante il processo UnPivot (prima di Pivoting alla fine) tutte le colonne vengono gettate in una singola colonna. Questo va bene per questo esempio, ma se stai mixando numeri, date e stringhe, ti suggerirei di lanciare tutto come un VarChar per evitare errori (e quindi ricorrere ai loro tipi di dati originali se necessario). – MikeTeeVee

0

penso che il caso in cui funzionerà solo se ci sono solo unici Weekno e DayofWeek in quanto restituirà solo i record di ultima inizio e di fine e filtrare il resto. Esempio

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 

Rinvierà solo la prima fila di weekno 1 di DayofWeek 2 e saltare la seconda fila.