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