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

Consulta do SQL Server:linhas fazem colunas (Pivot?)


Pivotar é muito parecido com agrupamento. Você pode vê-lo como um agrupamento limitado com um 'efeito especial'. A limitação consiste no fato de que só pode haver uma coluna agregada. (Na consulta GROUP BY normal, você pode ter mais de uma, naturalmente.) E pelo 'efeito especial' quero dizer, é claro, que uma das outras colunas (e, novamente, apenas uma) é transformada em várias colunas.

Vamos usar sua consulta GROUP BY como exemplo. Você tem três colunas na saída. Um deles, Count , é a própria coluna que contém informações agregadas. Essa é a que estaria espalhada entre várias colunas em uma consulta PIVOT. Outra coluna, Priority , é uma das duas outras colunas pelas quais os resultados são agrupados e também aquela que precisa ser dinamizada. Por fim, EntryDate é a outra coluna GROUP BY. Ele deve simplesmente ficar como está, porque não participa diretamente do pivô.

Vamos ver agora como seu SELECT principal é transformado de uma consulta GROUP BY usual em uma consulta PIVOT, passo a passo:

  1. Como o agrupamento está implícito em uma consulta PIVOT, a cláusula GROUP BY é removida. Em vez disso, uma cláusula PIVOT é introduzida.

  2. A Count a expressão da coluna é movida da cláusula SELECT para a cláusula PIVOT.

  3. A divisão da Priority coluna é definida na cláusula PIVOT.

  4. A Priority e Count as colunas na cláusula SELECT são substituídas pela lista das colunas definidas na cláusula PIVOT.

  5. A EntryDate coluna permanece inalterada na cláusula SELECT.

E aqui está a consulta resultante, com comentários marcando cada parte da transformação descrita acima:
WITH TATH(Priority, EntryDate) AS 
(
    SELECT TH.Priority as Priority, DATEADD(dd, 0, DATEDIFF(dd, 0, entryDate)) as EntryDate
      FROM TicketAssignment TA, TicketHeader TH 
     WHERE TA.TicketID = TH.TicketID   
       AND TA.Company = 'IT'
       AND TA.CurrentRole IN ('SA1B','SA1C','SDA')
) 
SELECT
  convert(varchar(10), EntryDate,103) as EntryDate,                       -- #5
  [0] AS Priority0, [1] AS Priority1, [2] AS Priority2, [3] AS Priority3  -- #4
FROM TATH
PIVOT (                                                                   -- #1
  COUNT(*)                                                                -- #2
  FOR Priority IN ([0], [1], [2], [3])                                    -- #3
) p

/*  -- your original main query, for comparison
SELECT
  Priority,                                                               -- #4
  convert(varchar(10),                                                    -- #5
  EntryDate,103) as EntryDate, COUNT(*) AS Count                          -- ##2&4
FROM TATH 
GROUP BY Priority, EntryDate                                              -- #1
*/

Há uma nota adicional na lista de colunas na cláusula PIVOT. Antes de tudo, você deve entender que o conjunto resultante de uma consulta SQL deve ser fixo em termos de número de colunas e seus nomes. Isso significa que você deve enumerar explicitamente todas as colunas transformadas que deseja ver na saída. Os nomes são derivados dos valores da coluna que está sendo dinamizada, mas devem ser especificados como nomes , não como valores. É por isso que você pode ver colchetes ao redor dos números listados. Como os próprios números não atendem às regras para identificadores regulares , eles devem ser delimitados.

Você também pode ver que pode criar alias para colunas dinâmicas na cláusula SELECT como qualquer outra coluna ou expressão. Então, no final, você não precisa acabar com o sem sentido 0 , 1 etc. e, em vez disso, você pode atribuir a essas colunas os nomes que desejar.

Se você quiser que o número e/ou nomes das colunas dinâmicas sejam dinâmicos, você terá que construir a consulta dinamicamente, ou seja, coletar os nomes primeiro, então incorporá-los em uma string contendo o resto do query e invoque a query final com EXEC () ou EXEC sp_executesql . Você pode pesquisar neste site para obter mais informações sobre a dinâmica dinâmica.