Tsql 使用另一个表中的字段作为列标题创建视图

Tsql 使用另一个表中的字段作为列标题创建视图,tsql,Tsql,我有两张桌子要合并成一个视图。第一个表包含以下结构: 模板表 第二个表包含将要存储的实际数据,列引用第一个表的ID: 数据表 我希望在视图中得到的结果: 组合表/视图 这可能吗?我一直在尝试让它与pivot表一起工作,但我一直在考虑如何使用标题作为数据的列。这些行中的一些内容 DECLARE @f0 VARCHAR(50)=(SELECT title FROM template WHERE componentID=1000) DECLARE @f1 VARCHAR(50)=(SELECT tit

我有两张桌子要合并成一个视图。第一个表包含以下结构:

模板表

第二个表包含将要存储的实际数据,列引用第一个表的ID:

数据表

我希望在视图中得到的结果:

组合表/视图


这可能吗?我一直在尝试让它与pivot表一起工作,但我一直在考虑如何使用标题作为数据的列。

这些行中的一些内容

DECLARE @f0 VARCHAR(50)=(SELECT title FROM template WHERE componentID=1000)
DECLARE @f1 VARCHAR(50)=(SELECT title FROM template WHERE componentID=1001)
DECLARE @f2 VARCHAR(50)=(SELECT title FROM template WHERE componentID=1002)
@sql='SELECT field1000 AS ' + quotename(@f0)  + ' field1001 AS ' + quotename(@f1)  + ' field1002 AS ' + quotename(@f2) + ' FROM data'
exec sp_executesql @sql

好吧,我对这个有点过火了,但这会满足你的要求。此过程将所有字段与适当的数据表列组合在一起,不需要知道或关心数据表中有多少列

它不使用游标,但由于可能有许多模板表,它确实使用动态SQL为最终返回生成Select语句

唯一需要注意的是,它不是一个视图,而是一个存储过程,因为它允许为最终要从中选择的数据表传递变量

假设:

模板表是静态的 所有数据表都有一个模板表 任何数据表中的所有字段都必须是唯一的* 所有数据表都有一个PK/identity字段,其中包含一个必须忽略的单词“id” 数据表中的所有字段在模板表中都有相应的标题 根据您的示例,数据表中的所有字段都以单词“field”作为前缀,模板表中的所有引用ID都对应于已删除“field”的字段名称 *-当然,可以通过修改模板表模式来改进它,例如,为字段标题所属的数据表添加一个字段,这将删除此假设3

过程:

首先,我们需要字段名、引用ID和列标题的映射。我们使用一个表变量来实现这一点,并从syscolumns获取信息。然后,我们更新临时表以从TemplateTable表中获取标题

然后,我们需要从DataTable构建一个动态选择列表,DataTable是SP中的一个参数,因此需要执行一些动态SQL。我的首选方法是在源表中有一个可以更新的bit列,比如“IsCompleted”,然后使用常规While循环遍历每一行。在While循环中,我们所做的就是从临时表变量中获取当前titlerreference,并将上面第一步中syscolumns中的真实字段名附加到select列表中

最后,我们执行具有Select的动态SQL语句,当它位于所执行的存储过程中时,结果将作为存储过程的结果返回

完整的工作代码

结果


希望这有帮助,写它很有趣

阅读一下游标,它们可以用来实现这一点,这是实现我所寻找的结果的最佳或唯一的方法吗?正如你在下面看到的,这不是唯一的方法,但在我看来,它们非常有用。我更多地考虑的是动态查询,您可能不知道其中的所有列。由于第一个模板表中的行数可能会发生变化,因此最好不要硬编码id号。我最后使用了此方法并做了一些调整:我更改了动态查询以创建或更改视图,并添加了另一个while循环来重命名任何重复的列,以确保视图不会失败。谢谢你的帮助!
id | field1000 | field1001 | field1002
======================================
1  | navy      | ruby      | vermilion
2  | midnight  | crimson   | amber
id | blue     | red     | orange
=================================
1  | navy     | ruby    | vermilion
2  | midnight | crimson | amber
DECLARE @f0 VARCHAR(50)=(SELECT title FROM template WHERE componentID=1000)
DECLARE @f1 VARCHAR(50)=(SELECT title FROM template WHERE componentID=1001)
DECLARE @f2 VARCHAR(50)=(SELECT title FROM template WHERE componentID=1002)
@sql='SELECT field1000 AS ' + quotename(@f0)  + ' field1001 AS ' + quotename(@f1)  + ' field1002 AS ' + quotename(@f2) + ' FROM data'
exec sp_executesql @sql
Create Procedure usp_CombineTables
(
    @DataTableName varchar(50)
)
As
    -- Test
    -- Exec usp_CombineTables 'DataTable'

    -- Set up our variables
    Declare @DataTableIdFieldName varchar(50),  -- The ID field of the data table, dynamic
            @IsCompleted bit,                   -- Used by While loop to know when to exit
            @CurrentTitleReference  int,        -- Used in While loop as the ID from TemplateTable that relates to the real data field name and the desired title 
            @CurrentDataFieldName varchar(50),  -- Used in While loop for the current actual field name in the data table
            @CurrentTitle varchar(50),          -- Used in While loop for the desired field name in the resulting table of the stored proc
            @DynamicSelectQuery varchar(2000)   -- Stores the SQL query that is dynamically built and executed for the final result; can increase value if needed

    -- Use table variable to correlate the datatable columns, titles, and references
    Declare @TitleReferences Table (
        TitleReference int,
        DataTableColumnName varchar(50),
        Title varchar(50),
        Completed bit default 0
    )

    -- Get the info from syscolumns about our datatable; assumes that all of the field names are prefixed with the word 'field' which needs to be removed
    Insert Into @TitleReferences ( 
        TitleReference,
        DataTableColumnName
    )
    Select 
        Replace(name, 'field', '') As TitleReference,
        name As DataTableColumnName
    From syscolumns 
    Where id = OBJECT_ID(@DataTableName)
        And name Not Like '%id%' -- assumes DataTable will always have a PK with 'id' in it, need to ignore/remove

    -- Get the titles -- assumes only one template table for all data tables; all data fields accross tables must be unique
    Update @TitleReferences
        Set Title = t.Title From TemplateTable As t
        Where TitleReference = t.ComponentID

    -- Get the ID field of the data table
    Set @DataTableIdFieldName = (
        Select name From syscolumns 
        Where id = OBJECT_ID(@DataTableName)
        And name Like '%id%')

    -- Build a dynamic SQL query to select from the datatable with the right column names
    Set @DynamicSelectQuery = 'Select ' + @DataTableIdFieldName + ', ' -- start with the ID
    Set @IsCompleted = 0
    While (@IsCompleted = 0)
        Begin
            -- Retrieve the field name and title from the current row based on title reference
            Set @CurrentTitleReference = (Select Top 1 TitleReference From @TitleReferences Where Completed = 0)
            Set @CurrentDataFieldName = (Select DataTableColumnName From @TitleReferences Where TitleReference = @CurrentTitleReference)
            Set @CurrentTitle = (Select Title From @TitleReferences Where TitleReference = @CurrentTitleReference)

            -- Append the next select field to the dynamic query
            Set @DynamicSelectQuery = @DynamicSelectQuery + 
                @CurrentDataFieldName + ' As ' + QuoteName(@CurrentTitle)

            -- Set up to move past current record in next iteration
            Update @TitleReferences Set Completed = 1 Where TitleReference = @CurrentTitleReference

            -- Exit loop or add comma for next field
            If (Select Count(Completed) From @TitleReferences Where Completed = 0) = 0
                Begin
                    Set @IsCompleted = 1    
                End
            Else
                Begin
                    -- Add comma to select field for next column
                    Set @DynamicSelectQuery = @DynamicSelectQuery + ','
                End
        End

    -- Now the column list is built, just add the table and exec
    Set @DynamicSelectQuery = @DynamicSelectQuery + 
        ' From ' + @DataTableName

    Exec(@DynamicSelectQuery)