16

このトピックに関する別の質問を送信して申し訳ありませんが、これに関する多くの回答を読みましたが、うまくいかないようです。

参加して情報を取得する必要がある 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_ids を検索して書き出すことなく、必要なものを達成するためのチートコードがあるかどうか疑問に思っていました。PIVOT 関数が私が探しているものである可能性が高いことはわかっていますが、正しく動作させることができないようです。

あなたたちが助けてくれると思いますか?

4

5 に答える 5

32

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 |
于 2013-08-08T12:02:33.590 に答える
0

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;
于 2016-04-23T06:22:12.763 に答える
-1

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
于 2019-04-08T09:34:01.750 に答える