动态加入枚举表与其他表

时间:2014-10-08 17:22:54

标签: sql sql-server sql-server-2008 enums

我有下表。这些不是真正的表格,但概念就在这里。

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个连接。如果有其他选择,请告诉我。

1 个答案:

答案 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

就其本身而言,这将返回问题中所需的结果集,但可以调整为返回任何给定表/列数据集的视图定义,然后根据表/视图进一步调整。