Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

SQL server juntar tabelas e pivô


Isso deve funcionar:
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
;

Ou alternadamente:
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
;

Eles têm o mesmo conjunto de resultados e podem, de fato, ser tratados da mesma forma pelo otimizador de consulta, mas possivelmente não. A grande diferença entra em jogo quando você começa a colocar condições na Sale table—você deve testar e ver qual consulta funciona melhor.

Observação:é crucial ao usar PIVOT que apenas as colunas que devem fazer parte da saída resultante estão disponíveis. É por isso que as duas consultas acima têm subconsultas de tabela derivadas extras (SELECT ...) para que apenas colunas específicas sejam expostas. Todas as colunas que estão disponíveis para serem vistas pelo PIVOT que não estão listados na expressão pivô serão implicitamente agrupados e incluídos na saída final. Isso provavelmente não será o que você deseja.

Posso sugerir, no entanto, que você faça o pivotamento na camada de apresentação? Se, por exemplo, você estiver usando o SSRS, é muito fácil usar um controle de matriz que fará todo o giro para você. Isso é melhor, porque se você adicionar uma nova Category , você não terá que modificar todo o seu código SQL!

Existe uma maneira de localizar dinamicamente os nomes das colunas para dinamizar, mas envolve SQL dinâmico. Eu realmente não recomendo isso como a melhor maneira, embora seja possível.

Outra maneira que poderia trabalho seria pré-processar esta consulta, ou seja, definir um gatilho na Category tabela que reescreve uma visão para conter todas as categorias existentes que existem. Isso resolve muitos dos outros problemas que mencionei, mas, novamente, é melhor usar a camada de apresentação.

Observação :Se os nomes das colunas (que antes eram valores) têm espaços, são números ou começam com um número, ou não são identificadores válidos, você deve citá-los com colchetes como em PIVOT (Max(Value) FOR CategoryId IN ([1], [2], [3], [4])) P . Como alternativa, você pode modificar os valores antes que eles cheguem ao PIVOT parte da consulta para acrescentar algumas letras ou remover espaços, para que a lista de colunas não precise escapar. Para ler mais sobre isso, confira as regras para identificadores no SQL Server.