我试图在具有多个列的表中选择一个值,基于另一个表中的列id,如下所示
foo:
+-------+--------+--------+--------+
| id | tag | col1 | col2 |
+-------+--------+--------+--------+
| 1 | XX | 1 | 2 |
+-------+--------+--------+--------+
bar:
+-------+--------+--------+
| id | field | tag |
+-------+--------+--------+
| 1 | col1 | XX |
+-------+--------+--------+
| 2 | col2 | XX |
+-------+--------+--------+
我想我正在寻找的是像反射一样的机制,我可以根据该属性的名称映射到属性值,而不必提前知道类或表,因为列可以更改随着时间的推移,结果表应该看起来像这样
foobar:
+--------+--------+
| tag | value |
--------++--------+
| XX | 1 |
--------++--------+
| XX | 2 |
--------++--------+
我尝试了类似下面的代码,但它在两个结果列中都给了我列id,我需要该特定字段的值而不是列的名称。
declare @SQL nvarchar(max)
declare @Pattern nvarchar(100)
set @Pattern = 'select bar.field, ''foo.[COL_NAME]'' as CurrentValue FROM bar INNER JOIN foo ON foo.[tag] = bar.[tag]'
select @SQL = stuff((select ' union all '+replace(@Pattern, '[COL_NAME]', field)
from bar
for xml path(''), type).value('.', 'nvarchar(max)'), 1, 11, '')
exec (@SQL)
答案 0 :(得分:1)
不要认为可以使用单个SQL语句动态地执行此操作。但是你可以用动态sql做到这一点。
使用给定的数据集,获得所需结果的最简单方法是使用case语句。
select foo.tag,
case
when bar.field = 'col1' then foo.col1
when bar.field = 'col2' then foo.col2
else null
end as value
from foo
inner join bar on foo.tag = bar.tag
只有when...then...
部分是动态的,但其余部分是静态的。因此,遍历bar
表以构建动态部分,然后将它们连接在一起。
declare @sql varchar(2000)
set @sql=''
select @sql = @sql +' when bar.field='''+field+''' then foo.' + field
from (select distinct field from bar) sub
--print @sql
set @sql = 'select foo.tag,
case ' + @sql + '
else null
end as value
from foo
inner join bar on foo.tag = bar.tag'
--print @sql
exec(@sql)