1

テーブル製品があり、各製品にはカテゴリとプロパティの動的リストがあります(これらのプロパティは別のテーブルにあります):

ProductCategories{ProductCategoryId, Name}
Products{ProductId, Name, ProductCategoryId}

ここで、あるカテゴリの製品をバインドします。ここで、各 ProductCategory は、そのカテゴリのプロパティを追加できる別のテーブルに関連付けられています。

CategoryProperties{CategoryPropertyId, ProductCategoryId, Name}

各プロパティの値を次の表に示します。

ProductPropertyValues{ProductId, CategoryPropertyId, Value}

問題は、クエリを実行するときです。

select p.Name as ProductName, m.Name as Manufacturer, pc.Name as Category
from products p
left join dbo.Manufacturers m
on p.ManufactureId = m.ManufactureId
left join dbo.ProductCategories pc
on p.ProductCategoryId = pc.ProductCategoryId

これにより、次のような結果が得られます。

| some product name | RedBull | Can |

しかし、この製品カテゴリに関連するすべてのプロパティを取得したいのですが、それが問題です。このクエリを試すと:

select p.Name as ProductName, m.Name as Manufacturer, pc.Name as Category, cp.Name,  ppv.Value
from products p
left join dbo.Manufacturers m
on p.ManufactureId = m.ManufactureId
left join dbo.ProductCategories pc
on p.ProductCategoryId = pc.ProductCategoryId

left join dbo.CategoryProperties cp
on pc.ProductCategoryId = cp.ProductCategoryId

left join dbo.ProductPropertyValues ppv
on p.ProductId = ppv.ProductId

結果の1行ではなく、このクエリの後、「121」の結果が得られます。何が間違っているのかわかりません。私は次のような結果を得たい:

| Product name      | Manufacturer | Category | prop1 | prop2     | prop3| Prop4          |      
| some product name | RedBull      | Can      | 34    | something | 45.6 | something else |

私は何が間違っているのですか、それともこれは不可能ですか?
私が理解しているように、ここでいくつかのクロス結合を取得します。 ここに画像の説明を入力

ここに画像の説明を入力 ここに画像の説明を入力

4

2 に答える 2

2

データにアクセスしようとしているようですPIVOT。これにより、行の値が取得され、列に変換されます。

変換するプロパティの数が決まっている場合は、クエリを次のようにハードコーディングできます。

select *
from
(
  select p.Name as ProductName, 
    m.Name as Manufacturer, 
    pc.Name as Category, 
    cp.Name,
    ppv.Value
  from products p
  left join dbo.Manufacturers m
    on p.ManufactureId = m.ManufactureId
  left join dbo.ProductCategories pc
    on p.ProductCategoryId = pc.ProductCategoryId
  left join dbo.CategoryProperties cp
    on pc.ProductCategoryId = cp.ProductCategoryId
  left join dbo.ProductPropertyValues ppv
    on p.ProductId = ppv.ProductId
    and cp.CategoryPropertyId = ppv.CategoryPropertyId
) src
pivot
(
  max(value)
  for Name in ([Code], [Data], etc)
) piv

値の数が不明な場合は、もう少し難しくなります。これを実行するには、動的 SQL を使用する必要があります。ハードコーディングされたバージョンから動的ソリューションに移行する方が簡単なので、静的バージョンを示しました。

動的バージョンの鍵は、列名を取得することです。完全なスクリプトは次のようになります。

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

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

set @query = 'SELECT ProductName, Manufacturer, Category,' + @cols + ' from 
             (
                select p.Name as ProductName, 
                  m.Name as Manufacturer, 
                  pc.Name as Category, 
                  cp.Name,  
                  ppv.Value
                from products p
                left join dbo.Manufacturers m
                  on p.ManufactureId = m.ManufactureId
                left join dbo.ProductCategories pc
                  on p.ProductCategoryId = pc.ProductCategoryId
                left join dbo.CategoryProperties cp
                  on pc.ProductCategoryId = cp.ProductCategoryId
                left join dbo.ProductPropertyValues ppv
                  on p.ProductId = ppv.ProductId
                  and cp.CategoryPropertyId = ppv.CategoryPropertyId
            ) x
            pivot 
            (
                max(value)
                for Name in (' + @cols + ')
            ) p '

execute(@query)
于 2013-03-02T15:37:09.017 に答える
1

クロスジョインについてのあなたの質問に答えるために、問題はあなたがに縛られていないということだと思いProductPropertyValuesますCategoryPropertiesProductPropertyValuesしたがって、各行のすべてのカテゴリのすべてのプロパティを取得しますCategoryProperties

さて、あなたが望むフォーマットを得る限り...それは「ピボット」と呼ばれます。なぜなら、垂直リスト(すべてのプロパティ)を取得し、それを「ピボット」して水平にレンダリングするからです。PIVOTSQL Serverにはコマンドがありますが、コーディング時に列名に使用するすべての値を知っている必要があるため、これを動的に行うのは困難 です。プロパティが「Prop1」、「Prop 2」などと呼ばれていることを知っていればそれは機能しますが、名前は製品によって異なると思います。

すべてのプロパティを1行にまとめるのはどの程度決心していますか?それは可能ですが、複雑になります。

于 2013-03-02T15:18:54.327 に答える