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.