SQL根据其他表中提到的列名动态应用联接



我有一个表格,例如临时

Id Col1 Col2 Col3
1  1     2    3

我有另一张表加入信息

Id SourceKey Table TargetKey
1  Col1       A     ColA
2  Col2       B     ColB
3  Col3       C     ColC

我想生成一个查询,它将动态添加内部联接子句,看起来像这个

SELECT * FROM temp 
INNER JOIN A ON Col1=ColA 
INNER JOIN B ON Col2=ColB 
INNER JOIN C ON Col3=ColC

有什么帮助吗?

做不到。

SQL需要在查询编译时了解这些内容,在查看任何数据之前,这样它就可以验证安全性并检查可能的索引。唯一接近于在查询编译时将数据视为列的查询元素是PIVOT关键字。

否则,您只需要使用CASE表达式列出每一组可能的列比较,或者在多个步骤上编写动态SQL,首先执行查询以查找所需的列/联接,使用这些结果构建新的查询字符串,然后执行刚创建的字符串。

根据Charlieface的评论,使用string_agg 更新答案

declare 
@dsql nvarchar(max)

select @dsql = 'select * from temp ' + string_agg(' join '+ Table + ' on ' + c ,' ') 
from (
select Table , string_agg ( SourceKey + ' = ' + TargetKey,' and ') c
from table1
group by Table ) t

select @dsql
EXECUTE sp_executesql @dsql

使用字符串聚合可以非常巧妙地构建动态SQL查询:

尽量弄清楚哪些位是静态的,哪些位是动态的。并使用PRINT @sql对生成的代码进行测试

DECLARE @sql nvarchar(max) = N'
SELECT *
FROM temp s
' +
(
SELECT STRING_AGG(CAST(
N'JOIN ' + QUOTENAME(SCHEMA_NAME(t.schema_id)) + N'.' + QUOTENAME(t.name) + N' AS T' + CAST(t.object_id AS nvarchar(10)) + N' 
ON s.' + QUOTENAME(j.SourceKey) + N' = T' + CAST(t.object_id AS nvarchar(10)) + N'.' + QUOTENAME(c.name)
AS nvarchar(max)), N' 
') WITHIN GROUP (ORDER BY j.Id)
FROM sys.tables t
JOIN sys.columns c ON c.object_id = t.object_id
JOIN joininfo j ON OBJECT_ID(j.[Table]) = t.object_id
AND j.TargetKey = c.name
);
PRINT @sql;   -- for testing
EXECUTE sp_executesql @sql;

如果您的SQL Server版本不支持STRING_AGG,则可以使用FOR XML PATH('')

最新更新