不明な列数でのSQL Server 2005ピボット
-
03-07-2019 - |
質問
次のようなデータセットを使用しています。
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
割り当ての名前と数は動的です。次のような結果を取得する必要があります。
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を使用してこのWITHOUTを実装します。それが不可能な場合は、動的SQLを使用した実例が機能します。
解決
動的な SQL
とは言わなかったことは知っていますが、それを直接 SQL
で行う方法は見当たりません。
ピボットテーブルで同様の問題に対する私の答えを確認すると、列の連結および SQL 2005のPIVOT
動的な SQL
はインジェクションに対して脆弱ではなく、禁止する正当な理由はありません。別の可能性(データの変更頻度が非常に低い場合)は、コード生成を行うことです。動的な SQL
の代わりに、 SQL
が定期的にストアドプロシージャに対して生成されます。
他のヒント
動的SQLを使用してこのデータを PIVOT
するには、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)
を参照してください。
結果は次のとおりです。
| STUDENTNAME | ASSIGNMENT 1 | ASSIGNMENT 2 | ASSIGNMENT 3 | TOTAL |
--------------------------------------------------------------------
| StudentA | 100 | 80 | (null) | 180 |
| StudentB | 100 | 80 | 100 | 280 |
これを行うことがわかった唯一の方法は、動的SQLを使用して、列ラベルを変数に入れることです。
information_schemaをクエリして列の名前と型を取得し、結果セットを作成するときに結果をサブクエリとして使用できます。ログインのアクセスを少し変更する必要があることに注意してください。
このデータがレポートで使用される場合、SSRSマトリックスを使用できます。結果セットから列を動的に生成します。何度も使用しました-動的なクロス集計レポートに非常によく機能します。
これは、動的SQLを使用した良い例です。 http://www.simple- talk.com/community/blogs/andras/archive/2007/09/14/37265.aspx
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
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