2008-10-17 14 views
16

Estoy trabajando con un conjunto de datos que se parece a lo siguiente.Pivote de SQL Server 2005 con un número desconocido de columnas

StudentName | AssignmentName | Grade 
--------------------------------------- 
StudentA  | Assignment 1 | 100 
StudentA  | Assignment 2 | 80 
StudentA  | Total   | 180 
StudentB  | Assignment 1 | 100 
StudentB  | Assignment 2 | 80 
StudentB  | Assignment 3 | 100 
StudentB  | Total   | 280 

El nombre y el número de asignaciones son dinámicos, lo que necesito para obtener resultados simlilar a lo siguiente.

Student  | Assignment 1 | Assignment 2 | Assignment 3 | Total 
-------------------------------------------------------------------- 
Student A | 100   | 80   | null   | 180 
Student B | 100   | 80   | 100   | 280 

Ahora Tu lugar ideal para ordenar la columna basada en una "fecha de vencimiento" que podrían ser incluidos/asociado con cada asignación. El total debe estar al final si es posible (se puede calcular y eliminar de la consulta si es posible)

Sé cómo hacerlo para las 3 asignaciones usando pivote simplemente nombrando las columnas, está tratando de hacer de una manera dinámica que aún no he encontrado una BUENA solución. Estoy tratando de hacer esto en SQL Server 2005

EDITAR

Idealmente me gustaría poner en práctica esto sin usar SQL dinámico, ya que es en contra de la política. Si no es posible ... entonces funcionará un ejemplo de trabajo con SQL dinámico.

Respuesta

11

Sé que dijiste no dinámico SQL, pero no veo ninguna manera de hacerlo en recto SQL.

Si se echa un vistazo a mis respuestas a problemas similares a Pivot Table and Concatenate Columns y PIVOT in sql 2005

La dinámica SQL no es vulnerable a la inyección, y no hay ninguna buena razón para prohibirlo. Otra posibilidad (si los datos cambian con poca frecuencia) es generar código: en lugar del SQL dinámico, el SQL se genera con un procedimiento almacenado de forma regular.

+0

El gran ejemplo de Cade parece que voy a tener que seguir esa ruta ... –

+0

¡Gracias por el enlace de referencia y por ejemplo! Tendré que hacerlo de esa manera, SQL dinámico parece tan SUCIO pero a veces necesario –

+0

Cade, ¡solo quería decir gracias de nuevo! Tengo esto funcionando como un mecanismo de relojería ahora de mi lado ... –

1

La única manera que he encontrado para hacer esto es usar SQL dinámico y poner las etiquetas de columna en una variable.

0

puede consultar information_schema para obtener los nombres y los nombres de columna, luego use el resultado como una subconsulta cuando construya su conjunto de resultados. Tenga en cuenta que es probable que tenga que cambiar el acceso de inicio de sesión un poco.

+0

Cuidado para enviar a un ejemplo? La única forma en que he encontrado ws para compilar la lista es usando SQL dinámico, y prefiero no –

+0

. No estoy seguro de que puedas alejarte del SQL dinámico porque la cláusula IN de PIVOT debe tener valores codificados. ninguna subselección está permitida allí. ¡Oh, cómo desearía que esto no fuera cierto! – BoltBait

0

Esto es lo mismo que PIVOT in sql 2005

Si estos datos son para el consumo, en un informe se puede utilizar una matriz de SSRS. Generará columnas dinámicamente desde el conjunto de resultados. Lo he usado muchas veces: funciona bastante bien para los informes dinámicos de tabla cruzada.

Aquí hay un buen ejemplo con sql dinámico. http://www.simple-talk.com/community/blogs/andras/archive/2007/09/14/37265.aspx

+0

Ese es un escenario diferente, debo conservar el orden ... –

-2
select studentname,[Assign1],[Assign2],[Assign3],[Total] 
from 
(
select studentname, assignname, grade from student 
)s 
pivot(sum(Grade) for assignname IN([Assign1],[Assign2],[Assign3],[Total])) as pvt 
+1

Agregue una explicación a su respuesta –

-1
SELECT TrnType 
INTO #Temp1 
FROM 
(
    SELECT '[' + CAST(TransactionType AS VARCHAR(4)) + ']' AS TrnType FROM tblPaymentTransactionTypes 
) AS tbl1 

SELECT * FROM #Temp1 

SELECT * FROM 
(
    SELECT FirstName + ' ' + LastName AS Patient, TransactionType, ISNULL(PostedAmount, 0) AS PostedAmount 
    FROM tblPaymentTransactions 
      INNER JOIN emr_PatientDetails ON tblPaymentTransactions.PracticeID = emr_PatientDetails.PracticeId 
      INNER JOIN tblPaymentTransactionDetails ON emr_PatientDetails.PatientId = tblPaymentTransactionDetails.PatientID 
         AND tblPaymentTransactions.TransactionID = tblPaymentTransactionDetails.TransactionID 
    WHERE emr_PatientDetails.PracticeID = 152 
) tbl 
PIVOT (SUM(PostedAmount) FOR [TransactionType] IN (SELECT * FROM #Temp1) 
) AS tbl4 
+0

esta respuesta necesita una señalización significativa para ir con el código o la traducción al dominio indicado de la pregunta. 'tblPaymentTransactionTypes' se pega claramente del código no relacionado. – chris

6

Para PIVOT estos datos utilizando SQL dinámico se puede utilizar el siguiente código en SQL Server 2005 +:

crear tabla:

CREATE TABLE yourtable 
    ([StudentName] varchar(8), [AssignmentName] varchar(12), [Grade] int) 
; 

INSERT INTO yourtable 
    ([StudentName], [AssignmentName], [Grade]) 
VALUES 
    ('StudentA', 'Assignment 1', 100), 
    ('StudentA', 'Assignment 2', 80), 
    ('StudentA', 'Total', 180), 
    ('StudentB', 'Assignment 1', 100), 
    ('StudentB', 'Assignment 2', 80), 
    ('StudentB', 'Assignment 3', 100), 
    ('StudentB', 'Total', 280) 
; 

cruzada dinámica :

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(AssignmentName) 
        from yourtable 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT StudentName, ' + @cols + ' from 
      (
       select StudentName, AssignmentName, grade 
       from yourtable 
      ) x 
      pivot 
      (
       min(grade) 
       for assignmentname in (' + @cols + ') 
      ) p ' 

execute(@query) 

Ver SQL Fiddle with Demo

El resultado es:

| STUDENTNAME | ASSIGNMENT 1 | ASSIGNMENT 2 | ASSIGNMENT 3 | TOTAL | 
-------------------------------------------------------------------- 
| StudentA |   100 |   80 |  (null) | 180 | 
| StudentB |   100 |   80 |   100 | 280 | 
+0

¿Qué pasa si tuviera que reemplazar nulo con cero? – Chirag

+0

@Chirag [ver mi respuesta aquí] (http://stackoverflow.com/questions/15150068/sql-using-isnull-with-dynamic-pivot/15156448#15156448) – Taryn

Cuestiones relacionadas