Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL Server Join-Tabellen und Pivot

Das sollte funktionieren:

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
;

Oder alternativ:

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
;

Diese haben die gleiche Ergebnismenge und können vom Abfrageoptimierer tatsächlich gleich behandelt werden, möglicherweise aber nicht. Der große Unterschied kommt zum Tragen, wenn Sie anfangen, Bedingungen für den Sale festzulegen Tabelle – Sie sollten testen und sehen, welche Abfrage besser funktioniert.

Hinweis:Es ist entscheidend, wenn Sie PIVOT verwenden dass nur die Spalten verfügbar sind, die Teil der resultierenden Ausgabe sein sollen. Aus diesem Grund haben die beiden obigen Abfragen zusätzliche abgeleitete Tabellenunterabfragen (SELECT ...) sodass nur bestimmte Spalten angezeigt werden. Alle Spalten, die für PIVOT verfügbar sind die nicht im Pivot-Ausdruck aufgeführt sind, werden implizit gruppiert und in die endgültige Ausgabe aufgenommen. Das ist wahrscheinlich nicht das, was Sie wollen.

Darf ich jedoch vorschlagen, dass Sie das Pivotieren in der Präsentationsebene vornehmen? Wenn Sie beispielsweise SSRS verwenden, ist es ganz einfach, eine Matrixsteuerung zu verwenden, die das gesamte Pivotieren für Sie übernimmt. Das ist am besten, denn dann fügen Sie eine neue Category hinzu , müssen Sie nicht Ihren gesamten SQL-Code ändern!

Es gibt eine Möglichkeit, die zu pivotierenden Spaltennamen dynamisch zu finden, aber dazu gehört dynamisches SQL. Ich empfehle das auch nicht wirklich als den besten Weg, obwohl es möglich ist.

Ein anderer Weg, der könnte Die Arbeit wäre, diese Abfrage vorzuverarbeiten – das heißt, einen Trigger auf die Category zu setzen Tabelle, die eine Ansicht so umschreibt, dass sie alle vorhandenen Kategorien enthält. Dies löst viele der anderen Probleme, die ich erwähnt habe, aber auch hier ist es am besten, die Präsentationsebene zu verwenden.

Hinweis :Wenn Ihre Spaltennamen (die früher Werte waren) Leerzeichen enthalten, Zahlen sind oder mit einer Zahl beginnen oder anderweitig keine gültigen Bezeichner sind, müssen Sie sie wie in PIVOT (Max(Value) FOR CategoryId IN ([1], [2], [3], [4])) P . Alternativ können Sie die Werte ändern, bevor sie zum PIVOT gelangen Teil der Abfrage, um einige Buchstaben voranzustellen oder Leerzeichen zu entfernen, sodass die Spaltenliste nicht maskiert werden muss. Weitere Informationen hierzu finden Sie in den Regeln für Identifikatoren im SQL-Server.