sql >> Database teknologi >  >> RDS >> Sqlserver

SQL server join tabeller og pivot

Dette burde virke:

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
;

Eller alternativt:

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
;

Disse har det samme resultatsæt og kan faktisk behandles på samme måde af forespørgselsoptimeringsværktøjet, men muligvis ikke. Den store forskel kommer i spil, når du begynder at sætte betingelser på Sale tabel – du bør teste og se, hvilken forespørgsel der fungerer bedst.

Bemærk:det er afgørende, når du bruger PIVOT at kun de kolonner, der skal være en del af det resulterende output, er tilgængelige. Dette er grunden til, at de to ovenstående forespørgsler har ekstra afledte tabelunderforespørgsler (SELECT ...) så kun specifikke søjler er eksponeret. Alle kolonner, der er tilgængelige for at blive set af PIVOT som ikke er angivet i pivotudtrykket, vil implicit blive grupperet på og inkluderet i det endelige output. Dette vil sandsynligvis ikke være, hvad du ønsker.

Må jeg dog foreslå, at du foretager pivotering i præsentationslaget? Hvis du f.eks. bruger SSRS, er det ret nemt at bruge en matrixkontrol, der gør alt pivotering for dig. Det er bedst, for så hvis du tilføjer en ny Category , vil du ikke have ændret al din SQL-kode!

Der er en måde at dynamisk finde kolonnenavnene til at pivotere, men det involverer dynamisk SQL. Jeg anbefaler det heller ikke som den bedste måde, selvom det er muligt.

En anden måde, som kunne arbejdet ville være at forbehandle denne forespørgsel – hvilket betyder at indstille en trigger på Category tabel, der omskriver en visning til at indeholde alle de eksisterende kategorier, der findes. Dette løser mange af de andre problemer, jeg har nævnt, men igen, det er bedst at bruge præsentationslaget.

Bemærk :Hvis dine kolonnenavne (som tidligere var værdier) har mellemrum, er tal eller begynder med et tal eller på anden måde ikke er gyldige identifikatorer, skal du citere dem med firkantede parenteser som i PIVOT (Max(Value) FOR CategoryId IN ([1], [2], [3], [4])) P . Alternativt kan du ændre værdierne, før de når til PIVOT del af forespørgslen for at sætte nogle bogstaver foran eller fjerne mellemrum, så kolonnelisten ikke behøver at escape. For yderligere læsning om dette, tjek reglerne for identifikatorer i SQL Server.




  1. Løkkeresultater BOB PHP

  2. Syntaksfejl nær 'af' i fuldtekstsøgebetingelsen 'kontrol af'

  3. Hvordan finder man tidligere post [n-per-group max(timestamp) <timestamp]?

  4. Fremskynd tekstsammenligninger (funktionsvektorer) med rumlige MySQL-funktioner