1

これを手伝ってください。私は完全に立ち往生しています。私はコーダーブロックか何かを持っています。

私は次の表を持っています

ID     Name        Cost     Included
----   ----------  -------  ----------
1      Package1    10.00    Yes
2      Package2    20.00    No
3      Package3    20.00    Yes

この情報をクロス集計して、次の例のように表示したいのですが、テーブルにはさらに多くの列があります。

Type        Package1     Package2       Package3
-----       ------------ -----------    ----------
Name        Package1     Package2       Package3
Cost        10.00        20.00          30.00
Included    Yes          No             Yes
4

4 に答える 4

5

製品比較リストを作成しようとしているように思えます。これが当てはまる場合は、最初にテーブルのピボットを解除してから、個々のレコードを結合します。

「transponded」部分は、列のピボットを解除します。すべての列は、互換性のある型であるか、互換性のある型に変換されている必要があります。varchar(100) を選択します。transponded は、ProductInfo からの ID、列名としてのタイプ、および対応する列の値としての値の 3 つの列を持つテーブルを返します。

パーツを選択すると、別の を追加することで、必要な数の製品に関する情報が結合されleft join transponded tn on t1.Type = tnType and tn.ID = @parameternます。この部分は面倒に思えますが、ピボットを使用してこの部分を実行しようとすると、適切な順序で列を取得できませんでした-タイプでソートされた名前をピボットします。ただし、動的な SQL 生成が必要になります。このソリューションは、一度に比較したい製品の最大数に十分な数の結合を追加することで修正されます。5を超えないと思います。

=1、=2、および =3 はパラメーターに置き換える必要があります。クエリは、ストアド プロシージャでホストする必要があります。

; with transponded as 
(
  select ID, Type, Value
    from 
    (
      select ID, 
             Name, 
             cast (Cost as varchar(100)) Cost, 
             cast (case when Included = 1 then 'Yes' else 'No' end as varchar(100)) Included
        from ProductInfo
    ) p
      unpivot (Value for Type in (Name, Cost, Included) ) a
)
select t1.Type, 
       t1.Value Product1, 
       t2.Value Product2, 
       t3.Value Product3
  from transponded t1
  left join transponded t2
         on t1.Type = t2.Type
        and t2.id = 2
   left join transponded t3
     on t1.Type = t3.Type
    and t3.id = 3
  where t1.id = 1

つまり、一度に 1 つのレコードを転送し、Type 列によって別の転送されたレコードに結合します。

ああ、ここに Sql Fiddle プレイグラウンドがあります。

于 2012-04-14T15:45:23.173 に答える
1

ピボットは列ごとに集計する必要があるため、これを行う簡単な方法はありません。入力テーブルに列を追加すると、コードが使用されている場所でコードが変更されるまでこれらの値が出力に表示されないというメンテナンスの問題が発生することを考えると、おそらくストアド プロシージャで一度実行するのが最善だと思います。入力テーブルのスキーマに基づいて、探している出力を動的に生成します。

提供されたデータを使用して、これを行う方法を示しました。このデータは一時テーブルに格納され (ストアド プロシージャは一時テーブルでは機能しないため、#temp ではありません)、次のように入力されます。

CREATE TABLE temp (
    _key int,
    package_name varchar(50),
    cost float,
    included bit
)

INSERT INTO temp VALUES(1,'Package1',    10.00,    1)
INSERT INTO temp VALUES(2,'Package2',    20.00,    0)
INSERT INTO temp VALUES(3,'Package3',    20.00,    1)

ストアド プロシージャは、@pivot_field パラメーターに基づいて値のリストを取得し、これらの値を列リストとして使用して、"Type" フィールドの後に挿入します。次に、ピボット フィールドと他のすべてのフィールドを結合して行を生成し、一度に 1 列ずつピボットします。手順は次のとおりです。

CREATE PROCEDURE usp_get_pivot (@table_name nvarchar(255), @pivot_field nvarchar(255)) AS
BEGIN
    CREATE TABLE #temp (val nvarchar(max))

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

    SET @sql = 'SELECT DISTINCT ' + @pivot_field + ' FROM ' + @table_name
    INSERT INTO #temp EXEC sp_executesql @sql;
    SET @cols = (SELECT '[' + val + '],' FROM #temp FOR XML PATH(''))
    SET @cols = SUBSTRING(@cols, 1, LEN(@cols)-1)

    SET @SQL = N'SELECT ''' + @pivot_field + ''' as [type], *
    FROM (SELECT ' + @pivot_field + ', ' + @pivot_field + ' as ' + @pivot_field + '1 FROM ' + @table_name + ') AS source_table
    PIVOT (max(' + @pivot_field + '1) FOR ' + @pivot_field + ' IN (' + @cols + ')) AS pivot_table'

    DECLARE csr CURSOR FOR 
        SELECT c.name FROM sys.columns c, sys.objects o 
        WHERE c.object_id = o.object_id AND o.name = @table_name
        AND c.name <> @pivot_field
        ORDER BY column_id

    OPEN csr
    FETCH NEXT FROM csr INTO @col
    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @sql = @sql + ' UNION ALL
        SELECT ''' + @col + ''' as [type], *
        FROM (SELECT ' + @pivot_field + ', CAST(' + @col + ' AS VARCHAR) AS ' + @col + ' FROM ' + @table_name + ') AS source_table
        PIVOT (max(' + @col + ') FOR ' + @pivot_field + ' IN (' + @cols + ')) AS pivot_table'
        FETCH NEXT FROM csr INTO @col
    END

    CLOSE csr
    DEALLOCATE csr
    DROP TABLE #temp
    EXEC sp_executesql @sql
END

手順を単純にコピーして管理スタジオに貼り付け、上記のデータを作成し、次の手順を実行できるはずです。

EXEC usp_get_pivot 'temp', 'package_name'
于 2012-04-14T15:11:44.580 に答える
0

パッケージの数が静的でない場合、選択肢はないと思います。PIVOT句は、静的/定義された数の列のみを生成できます。

複数のステートメントを使用してテーブルからテーブルへの書き換えを行うこともできますが、それでも静的な列数に直面する必要があります。

ただし、たとえば 10 に設定してから、最大 10 個のパッケージを表示し、パッケージが少ない場合は残りの列に NULL を入れることができます。

動的 SQL を使用して列数を動的にすることもできますが、これは頭痛の種になります。

このデータを Excel にエクスポートする場合 (SQL でピボットしないでください)、Excel で転置を行います (「特殊貼り付け」の下にあります)。

于 2012-04-14T13:13:37.470 に答える
0

基本的に、この段階で私が持っているものは次のとおりです。

        SELECT [Type],
            MAX(Beginner) AS [Beginner],
            MAX(Intermediate) AS [Intermediate],
            MAX(Advanced) AS [Advanced]
    FROM
    (
        SELECT 
            'Name' AS TYPE,
            CASE WHEN Name='Beginner' THEN Name END AS [Beginner],
            CASE WHEN Name='Intermediate' THEN Name END AS [Intermediate],
            CASE WHEN Name='Advanced' THEN Name END AS [Advanced]
        FROM Administration.Package
        UNION ALL
        SELECT 
            'Price' AS TYPE,
            CASE WHEN Name='Beginner' THEN CAST(Price AS VARCHAR) END AS [Beginner],
            CASE WHEN Name='Intermediate' THEN CAST(Price AS VARCHAR) END AS [Intermediate],
            CASE WHEN Name='Advanced' THEN CAST(Price AS VARCHAR) END AS [Advanced]
        FROM Administration.Package
    )A
    GROUP BY [Type]

しかし、すべての列に共用体を使用するのは適切ではありません。

于 2012-04-14T13:14:50.417 に答える