web-dev-qa-db-ja.com

ビューでの動的ピボットSQLの使用

Gday All、

SQL Server:行を列に転置 のようにテーブルを動的にピボットするコードを記述しました。

コードは次のようになります

DECLARE @cols NVARCHAR(MAX), @sql NVARCHAR(MAX)

SET @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(FieldName)
            FROM CORE_Items_Extra
            WHERE Not(FieldName = '')
            ORDER BY 1
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)'),1,1,'')

SET @sql = 'SELECT ItemID, ' + @cols + '
              FROM
            (
              SELECT ItemID,  FieldValue, FieldName
                FROM CORE_Items_Extra
            )  AS SourceTable
            PIVOT
            (
              MAX(FieldValue) FOR FieldName IN (' + @cols + ')
            ) AS PivotTable;'

EXECUTE(@sql)

これは完全に機能しますが、ビュー内で使用したいのですが、コードをビューにコピーしようとしましたが、機能しますが、ビューのDeclareステートメントが気に入らないため、保存されません。ストアドプロシージャがビューでストアドプロシージャを使用できないため、テーブル値関数として使用する必要があると思いますが、TBF内でExecuteステートメントを使用できません。このデータをビュー内の別のテーブルと組み合わせる必要があり、動的に保ちたいので、どんなアイデアでも大歓迎です:) SQL 2008R2を使用しています

7
David Mayfield

ビュー(以下のサンプルではmyView)を作成してから、次のようにビューを変更するストアドプロシージャを作成することをお勧めします。

CREATE VIEW myView
AS
SELECT 1
GO

CREATE PROCEDURE myStoredProc
AS
BEGIN
    DECLARE @cols NVARCHAR(MAX), @sql NVARCHAR(MAX)

    SET @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(FieldName)
                FROM CORE_Items_Extra
                WHERE Not(FieldName = '')
                ORDER BY 1
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)'),1,1,'')

    SET @sql = 'ALTER VIEW myView
                AS
                SELECT ItemID, ' + @cols + '
                  FROM
                (
                  SELECT ItemID,  FieldValue, FieldName
                    FROM CORE_Items_Extra
                )  AS SourceTable
                PIVOT
                (
                  MAX(FieldValue) FOR FieldName IN (' + @cols + ')
                ) AS PivotTable;'

    EXECUTE(@sql)
END
GO

これを1日に1回以上ジョブ内でSP)実行します。

4
gofr1

あなたがやろうとしていることを考えると、唯一の選択肢はこれにストアドプロシージャを使用することだと思います。ビューは、CTEおよび関数を含むSELECTステートメントに制限されています。より複雑な実行は機能しません。

他のいくつかのアイデア:

1)動作を非表示にする場合は、結果セットをテーブルに挿入し、動的コードを使用してプロシージャをスケジュールして、エージェントジョブまたはテーブルを更新する何かで毎日実行することができます。

2)データベーストリガーを確認し、ユーザーがSELECTを実行した時点で新しいデータでテーブルを更新します。これは理想的ではなく、同じデータセットを必要とするユーザーが多数いる場合は、パフォーマンスの問題が発生するため、非常に厄介な回避策になります。実際、なぜ私もこれを提案しているのですか。

1
Paul Andrew