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

SQL Server unisce tabelle e pivot

Questo dovrebbe funzionare:

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
;

O in alternativa:

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
;

Questi hanno lo stesso set di risultati e possono in effetti essere trattati allo stesso modo da Query Optimizer, ma forse no. La grande differenza entra in gioco quando inizi a porre condizioni sulla Sale tabella:dovresti testare e vedere quale query funziona meglio.

Nota:è fondamentale quando si utilizza PIVOT che siano disponibili solo le colonne che dovrebbero far parte dell'output risultante. Questo è il motivo per cui le due query precedenti hanno sottoquery di tabelle derivate aggiuntive (SELECT ...) in modo che siano esposte solo colonne specifiche. Tutte le colonne che possono essere visualizzate da PIVOT che non sono elencati nell'espressione pivot verranno implicitamente raggruppati e inclusi nell'output finale. Probabilmente non sarà ciò che desideri.

Posso suggerire, tuttavia, di eseguire il pivoting nel livello di presentazione? Se, ad esempio, stai usando SSRS, è abbastanza facile usare un controllo a matrice che farà tutto il pivoting per te. È la cosa migliore, perché se aggiungi una nuova Category , non dovrai modificare tutto il tuo codice SQL!

C'è un modo per trovare dinamicamente i nomi delle colonne su cui eseguire il pivot, ma coinvolge SQL dinamico. Non lo consiglio nemmeno come il modo migliore, anche se è possibile.

Un altro modo che potrebbe il lavoro consisterebbe nel preelaborare questa query, il che significa impostare un trigger sulla Category tabella che riscrive una vista per contenere tutte le categorie esistenti. Questo risolve molti degli altri problemi che ho menzionato, ma ancora una volta, usare il livello di presentazione è il migliore.

Nota :Se i nomi delle colonne (che in precedenza erano valori) hanno spazi, sono numeri o iniziano con un numero, o altrimenti non sono identificatori validi, devi citarli tra parentesi quadre come in PIVOT (Max(Value) FOR CategoryId IN ([1], [2], [3], [4])) P . In alternativa, puoi modificare i valori prima che arrivino al PIVOT parte della query per anteporre alcune lettere o rimuovere gli spazi, in modo che l'elenco delle colonne non debba essere modificato. Per ulteriori letture su questo, controlla le regole per gli identificatori in SQL Server.