このトピックについて別の質問を提出して申し訳ありませんが、これに関する多くの回答を読んだので、うまく機能しないようです。
参加して情報を取得する必要がある3つのテーブルがあります。テーブルの1つは3列のみであり、データを垂直方向に格納します。そのデータを水平形式に転置したいと思います。
参加してプルするだけの場合、データは次のようになります。
SELECT
a.app_id,
b.field_id,
c.field_name,
b.field_value
FROM table1 a
JOIN table2 b ON a.app_id = b.app_id
JOIN table3 c ON b.field_id = c.field_id --(table3 is a lookup table for field names)
結果:
app_id | field_id | field_name | field_value
-----------------------------------------------------
1234 | 101 | First Name | Joe
1234 | 102 | Last Name | Smith
1234 | 105 | DOB | 10/15/72
1234 | 107 | Mailing Addr | PO BOX 1234
1234 | 110 | Zip | 12345
1239 | 101 | First Name | Bob
1239 | 102 | Last Name | Johnson
1239 | 105 | DOB | 12/01/78
1239 | 107 | Mailing Addr | 1234 N Star Ave
1239 | 110 | Zip | 12456
代わりに、次のようにします。
app_id | First Name | Last Name | DOB | Mailing Addr | Zip
--------------------------------------------------------------------------
1234 | Joe | Smith | 10/15/72 | PO BOX 1234 | 12345
1239 | Bob | Johnson | 12/01/78 | 1234 N Star Ave | 12456
以前は、データで必要なすべてのfield_idを調べることに頼り、それぞれにCASEステートメントを作成していました。ユーザーが使用しているアプリには複数の製品のデータが含まれており、各製品には異なるフィールドが含まれています。サポートされる製品の数と各製品のフィールドの数(上で示した基本的な例よりもはるかに多い)を考慮すると、それらを検索して巨大なCASEステートメントのチャンクを書き出すには長い時間がかかります。
私は、field_idを調べて書き出すことなく、必要なものを達成するためのチートコードがそこにあるかどうか疑問に思っていました。 PIVOT関数が私が探しているものである可能性が高いことはわかっていますが、正しく機能させることができません。
あなたたちが手助けできると思いますか?
[〜#〜] pivot [〜#〜] 関数を使用して、データの行を列に変換できます。
元のクエリを使用してすべてのデータを取得できます。変更を加える唯一の変更は、列b.field_id
を除外することです。これにより、結果の最終的な表示が変更されます。
列に変換したいfield_name
値の既知のリストがある場合は、クエリをハードコーディングできます。
select app_id,
[First Name], [Last Name], [DOB],
[Mailing Addr], [Zip]
from
(
SELECT
a.app_id,
c.field_name,
b.field_value
FROM table1 a
INNER JOIN table2 b
ON a.app_id = b.app_id
INNER JOIN table3 c
ON b.field_id = c.field_id
) d
pivot
(
max(field_value)
for field_name in ([First Name], [Last Name], [DOB],
[Mailing Addr], [Zip])
) piv;
SQL Fiddle with Demo を参照してください。
ただし、field_name
の値の数が不明になる場合は、動的SQLを実装して結果を取得する必要があります。
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(Field_name)
from Table3
group by field_name, Field_id
order by Field_id
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT app_id,' + @cols + '
from
(
SELECT
a.app_id,
c.field_name,
b.field_value
FROM table1 a
INNER JOIN table2 b
ON a.app_id = b.app_id
INNER JOIN table3 c
ON b.field_id = c.field_id
) x
pivot
(
max(field_value)
for field_name in (' + @cols + ')
) p '
execute sp_executesql @query;
SQL Fiddle with Demo を参照してください。これらの両方で結果が得られます。
| APP_ID | FIRST NAME | LAST NAME | DOB | MAILING ADDR | Zip |
------------------------------------------------------------------------
| 1234 | Joe | Smith | 10/15/72 | PO Box 1234 | 12345 |
| 1239 | Bob | Johnson | 12/01/78 | 1234 N Star Ave | 12456 |
これを試して
SELECT
[app_id]
,MAX([First Name]) AS [First Name]
,MAX([Last Name]) AS [Last Name]
,MAX([DOB]) AS [DOB]
,MAX([Mailing Addr]) AS [Mailing Addr]
,MAX([Zip]) AS [Zip]
FROM Table1
PIVOT
(
MAX([field_value]) FOR [field_name] IN ([First Name],[Last Name],[DOB],[Mailing Addr],[Zip])
) T
GROUP BY [app_id]
bluefeetの答えは私にとって正しい答えでしたが、列リストで明確にする必要がありました。
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT Distinct ',' + QUOTENAME(Field_name)
from Table3
group by field_name, Field_id
order by ',' + QUOTENAME(Field_name)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT app_id,' + @cols + '
from
(
SELECT
a.app_id,
c.field_name,
b.field_value
FROM table1 a
INNER JOIN table2 b
ON a.app_id = b.app_id
INNER JOIN table3 c
ON b.field_id = c.field_id
) x
pivot
(
max(field_value)
for field_name in (' + @cols + ')
) p '
execute sp_executesql @query;
SQLピボットの使用法
SELECT [Id], [FirstName], [LastName], [Email]
FROM
(
SELECT Id, Att_Id, Att_Value FROM VerticalTable
) as source
PIVOT
(
MAX(Att_Value) FOR Att_Id IN ([FirstName], [LastName], [Email])
) as target