10

次のようなテーブル「プロパティ値」があります。

ID FileID プロパティ値
1 x Name 1.pdf
2 x Size 12567
3 x Type application/pdf
4 y Name 2.pdf
5 y Size 23576
6 y Type application/pdf
......
等々

上記のテーブルに SQL クエリを記述して、以下のような結果を取得する方法

 
FileID 名前 サイズ 種類
x 1.pdf 12567 アプリケーション/pdf
y 2.pdf 23576 アプリケーション/pdf
4

4 に答える 4

11

RDBMS を指定しませんでした。変換する列の数がわかっている場合は、値をハードコーディングできます。

select FileId,
  max(case when property = 'Name' then value end) Name,
  max(case when property = 'Size' then value end) Size,
  max(case when property = 'Type' then value end) Type
from yourtable
group by FileId

これは基本的にPIVOT関数です。一部の RDBMS には がありPIVOTます。その場合、次を使用PIVOTできます。SQL Server、Oracle で使用できます。

select *
from 
(
  select FileId, Property, Value
  from yourTable
) x
pivot
(
  max(value)
  for property in ([Name], [Size], [Type])
) p

変換する列の数が不明な場合は、動的を使用できますPIVOT。これは、実行時に変換する列のリストを取得します。

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

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

set @query = 'SELECT ' + @cols + ' from 
             (
                select FileId, Property, Value
                from yourtable
            ) x
            pivot 
            (
                max(value)
                for Property in (' + @cols + ')
            ) p '

execute(@query)
于 2012-09-27T10:49:51.943 に答える
9

欠落している行に関係なく機能する結合のあるバージョン:

SELECT  
    pd.FileID 
  , p1.Value  AS Name
  , p2.Value  AS Size
  , p3.Value  AS Type
FROM
        ( SELECT DISTINCT FileID
          FROM propertyvalues 
        ) AS pd
    LEFT JOIN
        propertyvalues AS p1
            ON  p1.FileID = pd.FileID 
            AND p1.Property = 'Name'
    LEFT JOIN
        propertyvalues AS p2
            ON  p2.FileID = pd.FileID 
            AND p2.Property = 'Size'
    LEFT JOIN
        propertyvalues AS p3
            ON  p3.FileID = pd.FileID
            AND p3.Property = 'Type' ;

が主キーであるテーブルがある場合は、サブクエリをそのテーブルにFileID置き換えることができます。DISTINCT


効率に関しては、多くの要因に依存します。例:

  • すべての FileID には、名前、サイズ、およびタイプを含む行があり、他のプロパティはありませんか (そして、テーブルにはクラスター化インデックスがあります(FileID, Property)か)? いずれにせよ、テーブル全体をスキャンする必要があるため、MAX(CASE...)バージョンは非常にうまく機能します。

  • (多くの) 3 つ以上のプロパティがあり、多くの FileID に名前、サイズ、およびタイプがない場合、このインデックス データのみが結合に使用されるため、JOINバージョンはインデックスでうまく機能します。(Property, FileID) INCLUDE (Value)

  • PIVOTバージョンがどれほど効率的かはわかりません。

ただし、使用するバージョンを選択する前に、環境(バージョン、ディスク、メモリ、設定など)でデータとテーブルのサイズを使用してさまざまなバージョンをテストすることをお勧めします。

于 2012-09-27T11:56:45.617 に答える
-1
select 
  p1.FileID as FileID,
  p1.Value as Name,
  p2.Value as Size,
  p3.Value as Type
from 
  propertyvalues as p1 join 
  propertyvalues as p2 on p1.FileID = p2.FileID join 
  propertyvalues as p3 on p1.FileID = p3.FileID
where
  p1.Property='Name' AND p2.Property='Size' AND p3.Property='Type'
于 2012-09-27T10:54:04.013 に答える