2009-11-05 24 views
7

Digamos que tengo algunos datos, ya sea en una tabla de SQL Server 2008 o una [Tabla] variable de -typed:El uso de PIVOT en SQL Server 2008

author_id  review_id  question_id  answer_id 
88540   99001   1    719 
88540   99001   2    720 
88540   99001   3    721 
88540   99001   4    722 
88540   99001   5    723 
36414   24336   1    302 
36414   24336   2    303 
36414   24336   3    304 
36414   24336   4    305 
36414   24336   5    306 

que desea recuperar los datos como un conjunto de resultados que se se ve así:

author_id  review_id  1  2  3  4  5 
88540   99001   719 720 721 722 723 
36414   24336   302 303 304 305 306 

sospecho que el operador PIVOT es lo que necesito (según this post, de todos modos), pero no puedo encontrar la manera de empezar a trabajar, sobre todo cuando el número de question_id filas la mesa puede variar En el ejemplo anterior, es 5, pero en otra consulta la tabla puede estar poblada con 7 preguntas distintas.

Respuesta

9

En realidad, será mejor que lo haga en el cliente. Supongamos que está utilizando Reporting Services, obtiene los datos según su primer conjunto de resultados y los muestra usando Matrix, con author_id y review_id en el Row Group, question_id en el Column Group y MAX (answer_id) en el medio.

Una consulta es factible, pero necesitaría SQL dinámico en este momento.

... algo así como:

DECLARE @QuestionList nvarchar(max); 
SELECT @QuestionList = STUFF(
(SELECT ', ' + quotename(question_id) 
FROM YourTable 
GROUP BY question_id 
ORDER BY question_id 
FOR XML PATH('')) 
, 1, 2, ''); 

DECLARE @qry nvarchar(max); 
SET @qry = ' 
SELECT author_id, review_id, ' + @QuestionList + 
FROM (SELECT author_id, review_id, question_id, answer_id 
     FROM YourTable 
    ) 
PIVOT 
(MAX(AnswerID) FOR question_id IN (' + @QuestionList + ')) pvt 
ORDER BY author_id, review_id;'; 

exec sp_executesql @qry; 
+0

Esto parece ser lo que necesito. Le daré una oportunidad e informaré, ¡gracias! –

+1

Tenga en cuenta la subconsulta. Si solo usa "SELECT * FROM YourTable", cualquier otra columna involucrada afectará la agrupación implícita que proporciona la función PIVOT. Y si tiene algún error, comente la línea 'exec', sustituyéndola por' select @ qry' –

+0

Nunca más uso [SELECT *] - siempre declaro explícitamente las columnas a las que accedo - por lo que no será un problema. Y sí, estaba usando [select @qry] por un tiempo para poder ver/depurar la sentencia SQL de generación antes de que se ejecutara. Tu código funcionó como lo prometiste, ¡muchas gracias por tu ayuda! –

0
select * 
from @t pivot 
(
    max(answer_id) for question_id in ([1],[2],[3],[4],[5]) 
) pivotT 

La única forma de variar la lista ([1], [2], [3], [4], [5]) sería para construir esta consulta en una cadena (dinámicamente) y luego ejecutar eso.

3

Here que tiene gran ejemplo y explicación.

En su caso sería así:

SELECT author_id, review_id, [1], [2], [3], [4], [5] 
FROM 
    (
     SELECT author_id, review_id, question_id, answer_id 
     FROM the_table 
    ) up 
PIVOT (MAX(answer_id) FOR question_id IN ([1],[2],[3],[4],[5])) AS pvt 
0

Ver this answer

Básicamente, se pre-inspeccionar los datos para obtener las columnas y luego dinámicamente generar el SQL utilizando la lista de pivote dinámico. Realmente no hay una forma no dinámica, porque la definición de las columnas en el conjunto que desea devolver no es fija.

2
SELECT author_id, review_id, [1], [2], [3], [4], [5] 
FROM 
    (
     SELECT author_id, review_id, question_id, answer_id 
     FROM the_table 
    ) up 
PIVOT (MAX(answer_id) FOR