1. ホーム
  2. sql

[解決済み] SQL Serverで複数行を複数列に動的に結合する

2022-03-07 14:51:43

質問

私は、Microsoft SQL Serverを使用して、以下のアクションを動的に実行する必要がある大規模なデータベーステーブルを持っています。

このような結果から

 badge   |   name   |   Job   |   KDA   |   Match 
 - - - - - - - - - - - - - - - -
 T996    |  Darrien |   AP    |   3.0   |   20
 T996    |  Darrien |   ADC   |   2.8   |   16
 T996    |  Darrien |   TOP   |   5.0   |   120

SQLを使ってこのような結果に。

badge   |   name   |  AP_KDA | AP_Match | ADC_KDA | ADC_Match | TOP_KDA | TOP_Match 
- - - - - - - - -
T996    |  Darrien |   3.0   |   20     |  2.8    |   16      |   5.0   |  120      

30行あっても、60列で1行にまとまります。

現在、ハードコーディングではできるのですが(下記の例参照)、ダイナミックにはできません。

Select badge,name,
(
 SELECT max(KDA)
 FROM table
 WHERE (h.badge = badge) AND (h.name = name) 
 AND (Job = 'AP')
) AP_KDA,
(
 SELECT max(Match)
 FROM table
 WHERE (h.badge = badge) AND (h.name = name) 
 AND (Job = 'AP')
) AP_Match,
(
 SELECT max(KDA)
 FROM table
 WHERE (h.badge = badge) AND (h.name = name) 
 AND (Job = 'ADC')
) ADC_KDA,
(
 SELECT max(Match)
 FROM table
 WHERE (h.badge = badge) AND (h.name = name) 
 AND (Job = 'ADC')
) ADC_Match,
(
 SELECT max(KDA)
 FROM table
 WHERE (h.badge = badge) AND (h.name = name) 
 AND (Job = 'TOP')
) TOP_KDA,
(
 SELECT max(Match)
 FROM table
 WHERE (h.badge = badge) AND (h.name = name) 
 AND (Job = 'TOP')
) TOP_Match
from table h

複数の行を1つの行にまとめることができるMSSQLステートメントが必要です。3列目( Job ) のコンテンツは、カラム 4 と 5 のヘッダー ( KDAMatch ) となり、新しいカラムになります。

で6つの異なる値がある場合 Job (例えば Job1 を通して Job6 ) の場合、結果は12カラムになります、例. Job1_KDA , Job1_Match , Job2_KDA , Job2_Match などを、バッジと名前ごとにグループ化したものです。

列3のデータをループするステートメントが必要で、ハードコードする必要はありません(可能性のある各列に対してクエリを繰り返す)。 Job を使用するか、テンポラリテーブルを使用します。

どのように解決するのですか?

動的SQLを使ってやるのですが、これでは( http://sqlfiddle.com/#!6/a63a6/1/0 ) PIVOTソリューションです。

SELECT badge, name, [AP_KDa], [AP_Match], [ADC_KDA],[ADC_Match],[TOP_KDA],[TOP_Match] FROM
(
SELECT badge, name, col, val FROM(
 SELECT *, Job+'_KDA' as Col, KDA as Val FROM @T 
 UNION
 SELECT *, Job+'_Match' as Col,Match as Val  FROM @T
) t
) tt
PIVOT ( max(val) for Col in ([AP_KDa], [AP_Match], [ADC_KDA],[ADC_Match],[TOP_KDA],[TOP_Match]) ) AS pvt

おまけ:PIVOTをダイナミックSQLと組み合わせる方法です( http://sqlfiddle.com/#!6/a63a6/7/0 しかし、これは私にとっては良い練習になりました。

SELECT badge, name, cast(Job+'_KDA' as nvarchar(128)) as Col, KDA as Val INTO #Temp1 FROM Temp 
INSERT INTO #Temp1 SELECT badge, name, Job+'_Match' as Col, Match as Val FROM Temp

DECLARE @columns nvarchar(max)
SELECT @columns = COALESCE(@columns + ', ', '') + Col FROM #Temp1 GROUP BY Col

DECLARE @sql nvarchar(max) = 'SELECT badge, name, '+@columns+' FROM #Temp1 PIVOT ( max(val) for Col in ('+@columns+') ) AS pvt'
exec (@sql)

DROP TABLE #Temp1