Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/197.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何处理从数据库中选择动态属性_Sql_Sql Server_Tsql_Pivot - Fatal编程技术网

Sql 如何处理从数据库中选择动态属性

Sql 如何处理从数据库中选择动态属性,sql,sql-server,tsql,pivot,Sql,Sql Server,Tsql,Pivot,我设计了一个小数据库,其想法是我有一个表products,每个产品都有其类别和动态属性列表(这些属性在另一个表中): 我在这里绑定某个类别的产品。现在,每个ProductCategory都与另一个表相关,我可以在其中为该类别添加属性: CategoryProperties{CategoryPropertyId, ProductCategoryId, Name} 每个属性的值在此表中: ProductPropertyValues{ProductId, CategoryPropertyId, Va

我设计了一个小数据库,其想法是我有一个表products,每个产品都有其类别和动态属性列表(这些属性在另一个表中):

我在这里绑定某个类别的产品。现在,每个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 |
| Product name      | Manufacturer | Category | prop1 | prop2     | prop3| Prop4          |      
| some product name | RedBull      | Can      | 34    | something | 45.6 | something else |
但是我想获得和这个产品类别的所有相关属性,这就是问题所在。当我尝试此查询时:

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
在这个查询而不是结果中的一行之后,我得到了'121'结果。 我不知道我做错了什么。 我希望得到如下结果:

| some product name | RedBull | Can |
| Product name      | Manufacturer | Category | prop1 | prop2     | prop3| Prop4          |      
| some product name | RedBull      | Can      | 34    | something | 45.6 | something else |
我做错了什么,或者这是不可能的?
据我所知,这里有些交叉连接。


为了回答您关于交叉连接的问题,我认为问题在于您没有将
产品属性值
绑定到
类别属性
。因此,您可以从
ProductPropertyValues
中获取每个
CategoryProperty
行的所有类别的所有属性

现在,只要得到你想要的格式。。。这被称为“透视”,因为您希望获取一个垂直列表(所有属性)并“透视”它,水平呈现它。这很难动态完成,因为尽管SQL Server有一个
PIVOT
命令,但它要求您知道编码时要用于列名的所有值。如果你知道你的财产被称为“1号道具”、“2号道具”等,那就行了,但我认为这些名称会因产品而异


您如何确定将所有属性都放在一行中?这是可以做到的,但会很复杂

听起来好像您正试图
透视数据。这将获取行值并将其转换为列

如果要转换一组属性,则可以将查询硬编码为类似以下内容:

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
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)
如果有未知数量的值,它会变得更困难。您必须使用动态sql来执行此操作。我向您展示了一个静态版本,因为它更容易从硬编码版本转移到动态解决方案

动态版本的关键是获取列名。完整脚本将类似于以下内容:

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
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)

关于交叉连接,你是对的。我现在更改了查询,它返回11行。这正是我拥有的那类房产的数量。那部分是固定的,但我真的需要它在一排。我一整天都在苦苦挣扎:(@1110)你想展示的房产最多是多少?还是“不管有多少”?所有属性。所以第二个。@1110我本来想把你链接到上面bluefeet之前的一篇文章,但看起来他给了你相同的答案,是根据你的情况定制的。我可能会做得稍有不同,但想法是一样的。这是否意味着每个属性名称都必须有
Prop
前缀?@1110不,我是创建名为
Prop_
的列,然后在每个列的末尾附加一个行号值。因此,如果您有5个属性,那么您将有名为
Prop_1
Prop_2
等的列。我已经创建了一个表结构,您可以为一些示例数据和n在注释中发布新创建的架构链接?这将更容易与您的数据一起显示。在动态查询中,我在关键字“on”附近得到了不正确的语法:
fot this line
)t on p.ProductId
我现在尝试了它。但是我没有得到好的结果。我得到11行,但所有属性都有相同的值:(我用结果的图像更新了问题。@1110请参见我的编辑。您需要将
cp.Name
值转换为列。我已更新了脚本。