2010-11-24 15 views
2

J'ai la structure follwoing:Convertir des lignes à colonnes

Emp PayDate  Amount  
1 11/23/2010 500  
1 11/25/2010 -900  
1 11/28/2010 1000  
1 11/29/2010 2000  
2 11/25/2010 2000  
3 11/28/2010 -3000  
2 11/28/2010 4000  
3 11/29/2010 -5000 

J'ai besoin pour obtenir le résultat suivant si emp 1 est sélectionné (top 3 dates et leurs vals correspondantes - si elles existent - 4ème ligne est toujours ignorée)

PayDate1  Amount1 Paydate2  Amount2 Paydate3 Amount3 
11/23/2010 500  11/25/2010 -900  11/28/2010 1000 

Je dois obtenir le résultat suivant si emp 2 est sélectionné

Paydate1 Amount1 Paydate2  Amount2 Paydate3 Amount3 
11/25/2010 2000  11/28/2010 4000  NULL  NULL 

Je dois obtenir le résultat suivant si emp 3 est sélectionné

Paydate1  Amount1 Paydate2  Amount2 Paydate3 Amount3 
11/28/2010 -3000  11/29/2010 -5000 

Pour obtenir les données respectives dans les lignes que je peux exécuter la requête suivante:

select top 3 Paydate, Amount from Table where Emp = @Emp 

Mais comment puis-je obtenir le résultat d'une manière pivotante?

Répondre

0
CREATE TABLE dbo.Table1 
(
    Emp  int, 
    PayDate datetime, 
    Amount  int 
) 
GO 

INSERT INTO dbo.Table1 VALUES (1, '11/23/2010',500) 
INSERT INTO dbo.Table1 VALUES (1, '11/25/2010',-900) 
INSERT INTO dbo.Table1 VALUES (1, '11/28/2010',1000) 
INSERT INTO dbo.Table1 VALUES (1, '11/29/2010',2000) 
INSERT INTO dbo.Table1 VALUES (2, '11/25/2010',2000) 
INSERT INTO dbo.Table1 VALUES (3, '11/28/2010',-3000) 
INSERT INTO dbo.Table1 VALUES (2, '11/28/2010',4000) 
INSERT INTO dbo.Table1 VALUES (3, '11/29/2010',-5000) 


;WITH cte AS 
(SELECT Emp, PayDate, Amount, PayDateRowNumber 
FROM 
(SELECT Emp, 
     PayDate, 
     Amount, 
     ROW_NUMBER() OVER (PARTITION BY Emp ORDER BY PayDate) AS PayDateRowNumber 
FROM Table1) AS RankedTable1 
WHERE PayDateRowNumber < 4) 
SELECT c1.Emp AS Emp, c1.PayDate AS PayDate1 
     ,c1.Amount AS Amount1, c2.PayDate AS PayDate2 
     ,c2.Amount AS Amount2, c3.PayDate AS PayDate3, c3.Amount AS Amount3 
FROM cte c1 
LEFT JOIN cte c2 ON c2.Emp = c1.Emp AND c2.PayDateRowNumber = 2 
LEFT JOIN cte c3 ON c3.Emp = c2.Emp AND c3.PayDateRowNumber = 3 
WHERE c1.PayDateRowNumber = 1 

sortie est:

alt text

Certaines mises en garde sont qu'il ne sera pas le montant global pour le même employeur/jour (mais peut facilement être changé). Vous pouvez également modifier pour passer en revue l'utilisation de ROW_NUMBER() par rapport à RANK() et DENSE_RANK() en fonction de votre définition de "TOP 3"

1

Il existe un excellent article sur les pivots avec SQL Server 2005+ here.