Je suis confronté au défi suivant. J'ai besoin de faire pivoter les données du tableau deux fois sur la même colonne. Voici une capture d'écran des données.
Je veux avoir une ligne pour chaque ID d'article contenant à la fois la valeur d'achat et la valeur de vente pour chaque année. J'ai essayé de le faire en sélectionnant deux fois la colonne "année", en la formatant un peu pour que chaque année de vente soit précédée d'un "S" et chaque année d'achat commence par un "P", et en utilisant 2 pivots pour faire pivoter les colonnes de 2 ans . Voici la requête SQL (utilisée dans SQL Server 2008):
SELECT [Item ID],
[P2000],[P2001],[P2002],[P2003],
[S2000],[S2001],[S2002],[S2003]
FROM
(
SELECT [Item ID]
,'P' + [Year] AS YearOfPurchase
,'S' + [Year] AS YearOfSelling
,[Purchasing value]
,[Selling value]
FROM [ItemPrices]
) AS ALIAS
PIVOT
(
MIN ([Purchasing value]) FOR [YearOfPurchase] in ([P2000],[P2001],[P2002],[P2003])
)
AS pvt
PIVOT
(
MIN ([Selling value]) FOR [YearOfSelling] in ([S2000],[S2001],[S2002],[S2003])
)
AS pvt2
Le résultat n'est pas exactement ce que j'espérais (voir image ci-dessous):
Comme vous pouvez le voir, il existe toujours plus d'une ligne pour chaque ID d'élément. Existe-t-il un moyen de réduire le nombre de lignes à exactement un par article? Pour que cela ressemble un peu à la capture d'écran Excel ci-dessous?
Ma suggestion serait d'appliquer à la fois les fonctions UNPIVOT
et PIVOT
pour obtenir le résultat.
UNPIVOT
transformera les colonnes PurchasingValue
et SellingValue
en lignes. Une fois cela fait, vous pouvez faire pivoter les données dans votre résultat.
Le code sera:
select *
from
(
select itemid,
case
when col = 'PurchasingValue' then 'P'
when col = 'SellingValue' then 'S'
end + cast(year as varchar(4)) new_col,
value
from yourtable
unpivot
(
value
for col in ([PurchasingValue], [SellingValue])
) unpiv
) src
pivot
(
max(value)
for new_col in (P2000, P2001, P2002, P2003,
S2000, S2001, S2002, S2003)
) piv;
Voir SQL Fiddle with Demo . Le résultat est:
| ITEMID | P2000 | P2001 | P2002 | P2003 | S2000 | S2001 | S2002 | S2003 |
--------------------------------------------------------------------------
| 1 | 1000 | 1100 | 1200 | 1300 | 900 | 990 | 1080 | 1170 |
| 2 | 500 | 550 | 600 | 650 | 450 | 495 | 540 | 585 |
Dans SQL Server 2008+, vous pouvez utiliser CROSS APPLY
avec VALUES
avec la fonction PIVOT
:
select *
from
(
select itemid,
col+cast(year as varchar(4)) new_col,
value
from yourtable
cross apply
(
VALUES
(PurchasingValue, 'P'),
(SellingValue, 'S')
) x (value, col)
) src
pivot
(
max(value)
for new_col in (P2000, P2001, P2002, P2003,
S2000, S2001, S2002, S2003)
) piv
Voir SQL Fiddle with Demo
Un moyen simple de faire pivoter plusieurs colonnes consiste à simplement utiliser des expressions d'agrégation (cas).
SELECT [Item ID],
[P2000] = SUM(CASE WHEN [Year] = 2000 THEN [Purchasing value] END),
[P2001] = SUM(CASE WHEN [Year] = 2001 THEN [Purchasing value] END),
[P2002] = SUM(CASE WHEN [Year] = 2002 THEN [Purchasing value] END),
[P2003] = SUM(CASE WHEN [Year] = 2003 THEN [Purchasing value] END),
[S2000] = SUM(CASE WHEN [Year] = 2000 THEN [Selling value] END),
[S2001] = SUM(CASE WHEN [Year] = 2001 THEN [Selling value] END),
[S2002] = SUM(CASE WHEN [Year] = 2002 THEN [Selling value] END),
[S2003] = SUM(CASE WHEN [Year] = 2003 THEN [Selling value] END)
FROM ItemPrices
GROUP BY [Item ID]
Utilisez un GROUP BY ItemID, avec la fonction d'agrégation SUM (isnull (valeur, 0)) sur chacune des colonnes de résultats.