Dit zou moeten werken:
WITH Sales AS (
SELECT
S.SaleID,
S.SoldBy,
S.SalePrice,
S.Margin,
S.Date,
I.SalePrice,
I.Category
FROM
dbo.Sale S
INNER JOIN dbo.SaleItem I
ON S.SaleID = I.SaleID
)
SELECT *
FROM
Sales
PIVOT (Max(SalePrice) FOR Category IN (Books, Printing, DVD)) P
;
Of afwisselend:
SELECT
S.SaleID,
S.SoldBy,
S.SalePrice,
S.Margin,
S.Date,
I.Books,
I.Printing,
I.DVD
FROM
dbo.Sale S
INNER JOIN (
SELECT *
FROM
(SELECT SaleID, SalePrice, Category FROM dbo.SaleItem) I
PIVOT (Max(SalePrice) FOR Category IN (Books, Printing, DVD)) P
) I ON S.SaleID = I.SaleID
;
Deze hebben dezelfde resultatenset en kunnen in feite hetzelfde worden behandeld door de query-optimizer, maar mogelijk niet. Het grote verschil komt in het spel wanneer u voorwaarden begint te stellen aan de Sale
tabel - u zou moeten testen en zien welke query beter werkt.
Opmerking:het is cruciaal bij het gebruik van PIVOT
dat alleen de kolommen die deel moeten uitmaken van de resulterende uitvoer beschikbaar zijn. Dit is de reden waarom de twee bovenstaande query's extra afgeleide tabelsubquery's hebben (SELECT ...)
zodat alleen specifieke kolommen worden weergegeven. Alle kolommen die zichtbaar zijn voor PIVOT
die niet in de pivot-expressie worden vermeld, worden impliciet gegroepeerd op en opgenomen in de uiteindelijke uitvoer. Dit is waarschijnlijk niet wat je wilt.
Mag ik echter voorstellen dat u het draaien in de presentatielaag doet? Als u bijvoorbeeld SSRS gebruikt, is het vrij eenvoudig om een matrixbesturing te gebruiken die al het draaien voor u doet. Dat is het beste, want als je dan een nieuwe Category
toevoegt, , u hoeft niet al uw SQL-code te wijzigen!
Er is een manier om de kolomnamen dynamisch te vinden om te draaien, maar het gaat om dynamische SQL. Ik raad dat ook niet echt aan als de beste manier, hoewel het mogelijk is.
Een andere manier waarop zou werk zou zijn om deze query vooraf te verwerken, wat inhoudt dat een trigger wordt ingesteld op de Category
tabel die een weergave herschrijft om alle bestaande categorieën te bevatten. Dit lost veel van de andere problemen op die ik heb genoemd, maar nogmaals, het is het beste om de presentatielaag te gebruiken.
Opmerking :Als uw kolomnamen (die voorheen waarden waren) spaties bevatten, getallen zijn of beginnen met een getal, of anderszins geen geldige id's zijn, moet u ze tussen vierkante haken citeren zoals in PIVOT (Max(Value) FOR CategoryId IN ([1], [2], [3], [4])) P
. Als alternatief kunt u de waarden wijzigen voordat ze naar de PIVOT
gaan deel van de query om enkele letters voor te zetten of spaties te verwijderen, zodat de kolomlijst geen escapetekens nodig heeft. Voor meer informatie hierover, bekijk de regels voor identifiers in SQL Server.