我正在使用一个数据库,该数据库允许在“Item”表中存储“Custom Property”字段和每条记录。这是通过在Item表中通过[CustomString199],[CustomNumber00]到[CustomNumber199]和[CustomDate00]到[CustomDate00]通过[CustomString00]调用预设字段来完成的。还有另一个名为“CustomProperty”表的表,它将名称分配给每个自定义字段以及要在Item表中使用的列。这是它的外观。
Item:
| Id | CustomString00| ... | CustomString199 | CustomNumber00 | ... | CustomNumber199 | CustomDate00 | ... | CustomDate199 |
| 1 | 'IN REPAIR' | ... | NULL | 78.4 | ... | NULL | 2017-03-04 | ... | NULL |
| 2 | 'FINISHED' | ... | NULL | 68.5 | ... | NULL | 2017-03-05 | ... | NULL |
| 3 | 'WIP' | ... | NULL | NULL | ... | NULL | 2017-03-07 | ... | NULL |
CustomProperty:
| Name | Type| ColumnName |
| 'Status' | 0 | 'CustomString00' |
| 'Temperature' | 1 | 'CustomNumber00' |
| 'Made Date' | 2 | 'CustomDate00' |
对于定义的每个自定义属性,CustomProperty表中将有一条记录,它将指示它是什么数据类型以及该属性使用哪个列。目前,每种类型最多可定义200个自定义属性,即200 Text,200 Date和200 Numeric。用户根据需要定义自定义属性。如果用户仅使用55个自定义属性,则不会使用Item表中的许多字段。
我想创建一个更“友好”的视图,以便我们的用户可以创建自己的报告来显示这些属性。此视图将使用这两个表来创建一个如下所示的新表:
| Id | Status | Temperature | Made Date |
| 1 | 'IN REPAIR' | 78.4 | 2017-03-04 |
| 2 | 'FINISHED' | 68.5 | 2017-03-05 |
| 3 | 'WIP' | NULL | 2017-03-07 |
此视图应显示Custom Property表中定义的每个属性的列。对于此示例,仅定义了3个自定义属性,因此在此视图中显示3个字段。如果定义了所有600个自定义属性,则此视图中将有600个字段。如果在Item表中为该Custom属性存储了值,则会显示该值。如果没有值,那么将为该属性显示NULL(如第3项的温度所示)。
使用动态SQL我有一些结果,但不是我想要的。我做了一个查询,取消隐藏自定义属性字段并返回像这样的项的结果:
| Id | CPName | CPTextValue | CPNumberValue | CPDateValue |
| 1 | 'Status' | 'IN REPAIR' | NULL | NULL |
| 1 | 'Temperature' | NULL | 78.4 | NULL |
| 1 | 'Made Date' | NULL | NULL | 2017-03-04 |
| 2 | 'Status' | 'FINISHED ' | NULL | NULL |
| 2 | 'Temperature' | NULL | 68.5 | NULL |
| 2 | 'Made Date' | NULL | NULL | 2017-03-05 |
| 3 | 'Status' | 'WIP' | NULL | NULL |
| 3 | 'Made Date' | NULL | NULL | 2017-03-07 |
我的查询变得非常复杂,所以我想知道我是否采取了错误的方法。这是我到目前为止所做的。
DECLARE @textcolsUnpivot AS NVARCHAR(MAX),
@datecolsUnpivot AS NVARCHAR(MAX),
@numbercolsUnpivot AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @textcolsUnpivot
= stuff((select ','+quotename(columnname)
from customproperty
where custompropertytype = 0
order by columnname
for xml path('')), 1, 1, '')
select @datecolsUnpivot
= stuff((select ','+quotename(columnname)
from customproperty
where custompropertytype = 1
order by columnname
for xml path('')), 1, 1, '')
select @numbercolsUnpivot
= stuff((select ','+quotename(columnname)
from customproperty
where custompropertytype = 2
order by columnname
for xml path('')), 1, 1, '')
set @query
= 'select id, CPName, CPTextValue, NULL as CPDateValue, NULL as CPNumberValue from
(select id, CPTextValue, CPCol from item
unpivot
(
CPTextValue
for CPCol in ('+ @textcolsunpivot +')
) unpiv ) as pv
inner join
(select columnname, name as CPName, custompropertytype from customproperty) as cp
on cp.columnname = pv.CPCol
union
select id, CPName, NULL, CPDateValue, NULL from
(select id, CPDateValue, CPCol from item
unpivot
(
CPDateValue
for CPCol in ('+ @datecolsunpivot +')
) unpiv ) as pv
inner join
(select columnname, name as CPName, custompropertytype from customproperty) as cp
on cp.columnname = pv.CPCol
union
select id, CPName, NULL, NULL, CPNumberValue from
(select id, CPNumberValue, CPCol from item
unpivot
(
CPNumberValue
for CPCol in ('+ @numbercolsunpivot +')
) unpiv ) as pv
inner join
(select columnname, name as CPName, custompropertytype from customproperty) as cp
on cp.columnname = pv.CPCol
'
exec sp_executesql @query;
有关其他说明,表格的架构为:
Item:
Id - pk, (it's actually a GUID, but I'm using an int for this example.), not null
CustomString00 through CustomString199 - nvarchar(max), null
CustomDate00 through CustomDate199 - datetime, null
CustomNumber00 through CustomNumber199 - float, null
CustomProperty:
Name - nvarchar(100),not null
Type - int, not null
ColumnName - nvarchar(50), not null
如果我要继续我当前的方法,我想我现在需要将我之前查询的结果PIVOT,以便将其置于我正在寻找的形式中。这是对的吗?