我有下表。这些不是真正的表格,但概念就在这里。
Table1
----------------------------------
FieldID|EnumeratedValue|TextValue
----------------------------------
Col1 |1 |Hey
----------------------------------
Col1 |2 |Test
----------------------------------
Col1 |3 |George
----------------------------------
Col2 |1 |Random
----------------------------------
Col2 |2 |Wesley
----------------------------------
Col3 |1 |Tompson
----------------------------------
Col3 |2 |Oooo
----------------------------------
Table2
----------------------------------
Col1 |Col2 |Col3
----------------------------------
1 |2 |1
----------------------------------
2 |1 |1
----------------------------------
3 |1 |2
----------------------------------
期望的结果是视图
----------------------------------
Col1 |Col2 |Col3
----------------------------------
Hey |Wesley |Tompson
----------------------------------
Test |Random |Tompson
----------------------------------
George |Random |Oooo
----------------------------------
所以你可以写点像
SELECT col1.TextValue,col2.TextValue,col3.TextValue
FROM Table2 t2,
(SELECT * FROM Table1 WHERE FieldID = 'Col1') col1,
(SELECT * FROM Table1 WHERE FieldID = 'Col2') col2,
(SELECT * FROM Table1 WHERE FieldID = 'Col3') col3
WHERE t2.col1 = col1.EnumeratedValue and t2.col2 = col2.EnumeratedValue and t2.col3 = col3.EnumeratedValue
问题在于,在我们的实际表中,每个表中有大约20个这样的列。我想找一个更简单的方法来编写这段代码。我不想为我正在制作的每个视图硬编码20个连接。如果有其他选择,请告诉我。
答案 0 :(得分:3)
与任何变量连接解决方案一样,动态数据透视真的是更好的方式来看待它。它不像硬编码,非透视解决方案那样具有性能,但这将涉及最少的开发时间,并且可以适用于生成视图定义而不是制成表值函数(可以提供表名和可能是要转动和加入的列名称
首先,演示数据设置:
if object_id('dbo.test_enum') is not null drop table dbo.test_enum
create table dbo.test_enum (
FieldID sysname
, EnumeratedValue int not null
, TextValue sysname
, primary key (FieldID, EnumeratedValue)
)
INSERT INTO dbo.test_enum
(FieldID, EnumeratedValue, TextValue)
VALUES
('Col1', 1, 'Hey'),
('Col1', 2, 'Test'),
('Col1', 3, 'George'),
('Col2', 1, 'Random'),
('Col2', 2, 'Wesley'),
('Col3', 1, 'Tompson'),
('Col3', 2, 'Oooo')
;
if object_id('dbo.test_table') is not null drop table dbo.test_table
create table test_table (
id int primary key identity(1,1)
, Col1 int not null
, Col2 int not null
, Col3 int not null
);
INSERT INTO dbo.test_table
(Col1, Col2, Col3)
VALUES
(1,2,1),
(2,1,1),
(3,1,2)
接下来是动态选择部分:
declare @cols nvarchar(max) = (select stuff((
select ',' + quotename(c.name)
from sys.objects o
inner join sys.columns c on c.object_id = o.object_id
where o.name = 'test_table'
and c.name in ('Col1', 'Col2', 'Col3')
for xml path ('')
),1,1,''))
declare @SQL nvarchar(max) = N'
select p.id, ' + @cols + '
from (
select unp.id, unp.FieldID, e.TextValue
from dbo.test_table
unpivot (
EnumeratedValues FOR FieldID IN (' + @cols + ')
) unp
inner join dbo.test_enum e on e.EnumeratedValue = unp.EnumeratedValues
and e.FieldID = unp.FieldID
) z
pivot (
min(z.TextValue) FOR z.FieldID IN (' + @cols + ')
) p
'
exec sp_executesql @sql
就其本身而言,这将返回问题中所需的结果集,但可以调整为返回任何给定表/列数据集的视图定义,然后根据表/视图进一步调整。