1. ホーム
  2. sql

[解決済み] 集計を行わずに行から列へピボット移動する

2022-02-04 22:21:40

質問

ダイナミックピボットSPL文の書き方を考えています。 どこで TEST_NAME は最大 12 個の異なる値を持つことができます (従って 12 個の列を持つことになります)。 VALのいくつかは、Int、Decimal、またはVarcharデータ型になります。 私が見たほとんどの例では、何らかの集計が含まれています。 私は、ストレート・バリュー・ピボットを探しています。

Source Table 

╔═══════════╦══════╦═══════╗
║ TEST_NAME ║ SBNO ║  VAL  ║
╠═══════════╬══════╬═══════╣
║ Test1     ║    1 ║ 0.304 ║
║ Test1     ║    2 ║ 0.31  ║
║ Test1     ║    3 ║ 0.306 ║
║ Test2     ║    1 ║ 2.3   ║
║ Test2     ║    2 ║ 2.5   ║
║ Test2     ║    3 ║ 2.4   ║
║ Test3     ║    1 ║ PASS  ║
║ Test3     ║    2 ║ PASS  ║
╚═══════════╩══════╩═══════╝


Desired Output 
╔══════════════════════════╗
║ SBNO Test1 Test2   Test3 ║
╠══════════════════════════╣
║ 1    0.304  2.3    PASS  ║
║ 2    0.31   2.5    PASS  ║
║ 3    0.306  2.4    NULL  ║
╚══════════════════════════╝

解決方法は?

その PIVOT 関数が動作するようにするには、集約が必要です。 どうやらあなたの VAL カラムは varchar のどちらかを使用する必要があります。 MAX または MIN を集約した関数です。

テストの数が限られている場合は、値をハードコードすることができます。

select sbno, Test1, Test2, Test3
from
(
  select test_name, sbno, val
  from yourtable
) d
pivot
(
  max(val)
  for test_name in (Test1, Test2, Test3)
) piv;

参照 SQL Fiddle with Demo .

OPでは、カラムに変換する行の数が多くなると述べていますね。 もしそうであれば、動的SQLを使用することができます。

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(TEST_NAME) 
                    from yourtable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT sbno,' + @cols + '
             from 
             (
                select test_name, sbno, val
                from yourtable
            ) x
            pivot 
            (
                max(val)
                for test_name in (' + @cols + ')
            ) p '

execute(@query)

参照 SQL Fiddle with Demo .

どちらのバージョンも同じ結果になります。

| SBNO | TEST1 | TEST2 |  TEST3 |
---------------------------------
|    1 | 0.304 |   2.3 |   PASS |
|    2 |  0.31 |   2.5 |   PASS |
|    3 | 0.306 |   2.4 | (null) |