2008-10-17 74 views
16

我正在處理一組類似於以下內容的數據。SQL Server 2005支持未知列數

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個賦值,它正在嘗試它以一種動態的方式,我還沒有找到一個好的解決方案。我試圖做到這一點的SQL Server 2005

編輯

在理想情況下,我想實現這一點沒有使用動態SQL,因爲這是違反政策的。如果這是不可能的...那麼動態SQL的一個工作示例將起作用。

回答

11

我知道你說沒有動態SQL,但我沒有看到任何方式直接SQL

如果您在Pivot Table and Concatenate ColumnsPIVOT in sql 2005

動態SQL看看我的回答類似的問題沒有容易注入,並沒有很好的理由來禁止它。另一種可能性(如果數據很少發生變化)是執行代碼生成 - 而不是動態的SQLSQL定期生成到存儲過程。

+0

凱德偉大的例子看起來像我將不得不去那條路... – 2008-10-18 01:02:25

+0

感謝您的參考鏈接和示例!我只需要這樣做,動態SQL似乎很髒,但有時需要 – 2008-10-18 01:26:35

+0

凱德,我只是想再次表示感謝!我有這樣的工作就像現在在我身邊的發條... – 2008-10-22 06:43:01

1

我發現要做到這一點的唯一方法是使用動態SQL並將列標籤放入一個變量中。

0

您可以查詢information_schema以獲取列名稱和類型,然後在生成結果集時將結果用作子查詢。請注意,您可能需要稍微更改登錄的訪問權限。

+0

護理張貼了一個例子嗎?我發現ws使用動態SQL建立列表的唯一方法,我寧願不要 – 2008-10-17 20:30:51

+0

我不確定你能夠擺脫動態SQL,因爲PIVOT的IN子句必須具有硬編碼值 - 在那裏不允許再選擇。哦,我真希望這不是真的! – BoltBait 2008-10-17 20:49:53

-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

要使用動態SQL,你可以使用SQL Server 2005+下面的代碼PIVOT這樣的數據:

創建表:

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

動態PIVOT :

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 |