2008-10-17 2 views
16

Я работаю с набором данных, который выглядит примерно так:SQL Server 2005 Pivot on Unknown Number of Columns

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 

Название и количество заданий динамичны, мне нужно, чтобы получить результаты simlilar к следующему.

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

Теперь в идеале я хотел бы, чтобы отсортировать столбец, основанный на «срок», которые могут быть включены /, связанные с каждым заданием. Всего должно быть в конце концов, если это возможно (может быть вычислен и удаляются из запроса, если это возможно.)

Я знаю, как сделать это для 3-х заданий, используя стержень с просто именования столбцов, он пытается сделать это динамично, что я еще не нашел решение GOOD. Я пытаюсь сделать это на SQL Server 2005

EDIT

В идеале я хотел бы реализовать это без использования динамического SQL, так как это противоречит политике. Если это невозможно ... тогда будет работать рабочий пример с Dynamic SQL.

ответ

11

Я знаю, что вы сказали, что нет динамического SQL, но я не вижу никакого способа сделать это прямолинейно SQL.

Если вы проверить мои ответы на подобные проблемы в Pivot Table and Concatenate Columns и PIVOT in sql 2005

Динамический SQL там не уязвим для инъекций, и нет никаких оснований запрещать его. Другая возможность (если данные меняются очень редко) заключается в том, чтобы генерировать код - вместо динамического SQL, SQL генерируется в хранимую процедуру на регулярной основе.

+0

Cade отличный пример выглядит так, как будто мне нужно идти по этому маршруту ... – 2008-10-18 01:02:25

+0

Спасибо за ссылку ссылки и пример! Мне просто нужно идти так, динамический SQL просто кажется настолько DIRTY, но порой нужен – 2008-10-18 01:26:35

+0

Cade, я просто хотел еще раз поблагодарить! У меня это работает как часы, теперь на моей стороне .... – 2008-10-22 06:43:01

1

Единственный способ, которым я нашел это, - использовать динамический SQL и поместить метки столбца в переменную.

0

вы можете запросить информационную_схему, чтобы получить имена и типы столбцов, а затем использовать результат в качестве подзапроса при создании набора результатов. Обратите внимание, что вам, вероятно, придется немного изменить доступ к логину.

+0

Уход, чтобы развесить пример? Единственный способ, которым я нашел ws для создания списка с использованием динамического SQL, и я бы предпочел не – 2008-10-17 20:30:51

+0

Я не уверен, что вы сможете уйти от динамического SQL, потому что предложение PIVOT's IN должно иметь жестко закодированные значения - там не разрешено подзаголовок. О, как бы я хотел, чтобы это было неверно! – BoltBait 2008-10-17 20:49:53

0

Это то же самое, как PIVOT in sql 2005

Если эти данные для потребления в отчете можно использовать матрицу SSRS. Он будет генерировать столбцы динамически из набора результатов. Я использовал его много раз - он отлично работает для динамических отчетов кросс-таблицы.

Вот хороший пример с динамическим sql. http://www.simple-talk.com/community/blogs/andras/archive/2007/09/14/37265.aspx

-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
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 
6

Для PIVOT этих данных с помощью динамического SQL вы можете использовать следующий код в SQL Server 2005+:

Создать таблицу:

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) 
; 

Динамических Осевым :

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) 

См SQL Fiddle with Demo

Результат:

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