sql >> Database >  >> RDS >> Sqlserver

SQL server join-tabellen en pivot

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.




  1. importfout met python-mysql-connector 1.16, django 1.6 en python 3.2.3

  2. bereken een som van typetijd met behulp van sql

  3. Hibernate unie-subklasse (tabel per concrete klasse) mapping generator van increment erg traag?

  4. Selecteer alle optiewaarden php mysql