sql >> Databáze >  >> RDS >> Sqlserver

SQL Server dotaz:řádky tvoří sloupce (Pivot?)

Pivoting je velmi podobný seskupování. Můžete to vidět jako omezené seskupení se „zvláštním efektem“. Omezení spočívá v tom, že může být pouze jeden agregovaný sloupec. (V normálním dotazu GROUP BY můžete mít samozřejmě více než jeden.) A tím „zvláštním efektem“ mám samozřejmě na mysli, že jeden z ostatních sloupců (a opět pouze jeden) se transformuje do více sloupců.

Vezměme si jako příklad váš dotaz GROUP BY. Ve výstupu máte tři sloupce. Jeden z nich, Count , je samotný sloupec, který obsahuje agregované informace. To je ten, který by byl rozptýlen ve více sloupcích v PIVOT dotazu. Další sloupec, Priority , je jedním ze dvou dalších sloupců, podle kterých jsou výsledky seskupeny, a také sloupcem, který je třeba otočit. Nakonec EntryDate je druhý sloupec GROUP BY. Mělo by jednoduše zůstat tak, jak je, protože se přímo neúčastní otáčení.

Podívejme se nyní, jak se váš hlavní SELECT transformuje z obvyklého dotazu GROUP BY na dotaz PIVOT, krok za krokem:

  1. Protože seskupení je zahrnuto v dotazu PIVOT, klauzule GROUP BY je odstraněna. Místo toho je zavedena klauzule PIVOT.

  2. Count výraz sloupce se přesune z klauzule SELECT do klauzule PIVOT.

  3. Rozdělení Priority sloupec je definován v klauzuli PIVOT.

  4. Priority a Count sloupce v klauzuli SELECT jsou nahrazeny seznamem sloupců definovaných v klauzuli PIVOT.

  5. EntryDate sloupec zůstane v klauzuli SELECT nezměněn.

A zde je výsledný dotaz s komentáři označujícími každou část transformace popsané výše:

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
*/

V seznamu sloupců v klauzuli PIVOT je ještě jedna poznámka. Nejprve musíte pochopit, že výsledná sada SQL dotazu má být pevně daná, pokud jde o počet sloupců a jejich názvy. To znamená, že musíte explicitně vyjmenovat všechny transformované sloupce, které chcete vidět ve výstupu. Názvy jsou odvozeny z hodnot sloupce, který je pivotován, ale měly by být zadány jako názvy , ne jako hodnoty. Kolem uvedených čísel proto vidíte hranaté závorky. Protože samotná čísla nesplňují pravidla pro běžné identifikátory , musí být ohraničeny.

Můžete také vidět, že můžete alias pivotovaných sloupců v klauzuli SELECT stejně jako jakýkoli jiný sloupec nebo výraz. Takže nakonec nemusíte skončit u nic neříkajícího 0 , 1 atd. a místo toho můžete těmto sloupcům přiřadit libovolné názvy.

Pokud chcete, aby počet a/nebo názvy pivotovaných sloupců byly dynamické, budete muset vytvořit dotaz dynamicky, tj. nejprve shromáždit názvy a poté je začlenit do řetězce obsahujícího zbytek dotaz a vyvolejte konečný dotaz pomocí EXEC () nebo EXEC sp_executesql . Můžete prohledávat tento web pro více informací o dynamickém otáčení.




  1. jdbcTemplate je null a vyvolá výjimku null ukazatele

  2. MySQL Cursor Loop se neaktualizuje

  3. STRING_SPLIT() v SQL Server 2016:Následná akce #1

  4. Jak mohu vstoupit do SQL Server uloženého procesu z mého kódu C#?