2012-05-29 13 views
7

Ho scritto questa query:pivot con una quantità indefinita di valori distinti

SELECT s, [1] AS a1, [2] AS a2, [3] AS a3, [4] AS a4 
FROM (SELECT grade, aid, s FROM m) p 
PIVOT 
(
SUM(grade) 
FOR aid IN ([1], [2], [3], [4]) 
) AS pvt ORDER BY pvt.s; 

che restituisce il risultato:

s a1 a2 a3 a4 
1 25 69 95 56 
2 27 99 16 87 
. . . . 
99 98 12 34 76 

Che è esattamente il risultato che voglio. Il mio problema è che non ci saranno sempre quattro valori distinti in 'aiuti'. È possibile riscrivere questa query (o utilizzare una stored procedure) in modo che la quantità di colonne 'a *' dipenda dal numero di valori distinti in 'aiuto'?

risposta

11

Sarà necessario utilizzare un pivot dinamico per ottenere l'elenco di colonne che si desidera. Questo recupererà prima l'elenco delle colonne e quindi ruoterà quell'elenco. Qualcosa di simile a questo:

DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX); 

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(aid) 
      FROM m 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT s, ' + @cols + ' from 
      (
       select grade, aid, s 
       from m 
      ) x 
      pivot 
      (
       sum(grade) 
       for aid in (' + @cols + ') 
      ) p 
      ORDER BY p.s' 

execute(@query) 
+0

Wow grazie, è proprio quello che voglio! –

+1

+1 - Anche se per essere nitpicky, ti manca l'alias delle tue colonne – Lamak

2

Lamak: Ecco come l'ho fatto con gli alias di colonne. L'alias è collegato al valore di una colonna in un'altra tabella collegata da `aid '.

DECLARE 
    @cols AS NVARCHAR(MAX), 
    @colsAlias AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX); 

SELECT @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(aid) 
    FROM m 
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'') 

SELECT @colsAlias = STUFF((SELECT DISTINCT ',' + QUOTENAME(m.aid) + ' AS ' + QUOTENAME(n.aName) 
    FROM m INNER JOIN n ON m.aid = n.aid 
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'') 

SET @query = 'SELECT s, ' + @colsAlias + ' FROM 
       (
       SELECT grade, aid, s 
        FROM m 
       ) x 

      PIVOT 
      (
       MIN(grade) FOR aid IN (' + @cols + ') 
      ) p ' 

EXECUTE(@query) 
Problemi correlati