Sql 根据配置表从数据表中查找相应的值
我有两个表Sql 根据配置表从数据表中查找相应的值,sql,sql-server,sql-server-2012,Sql,Sql Server,Sql Server 2012,我有两个表PaymentData和PaymentDataConfig。有一个公共列id。表PaymentDataConfig有一个configColumn,其中包含表PaymentData中的列名称 if exists (select 1 from sys.objects o where o.[object_id] = object_id(N'PaymentData')) begin drop table PaymentData end create table PaymentDat
PaymentData
和PaymentDataConfig
。有一个公共列id
。表PaymentDataConfig
有一个configColumn
,其中包含表PaymentData
中的列名称
if exists (select 1 from sys.objects o where o.[object_id] = object_id(N'PaymentData'))
begin
drop table PaymentData
end
create table PaymentData
(
id int,
payment1 decimal(20,2),
payment2 decimal(20,2),
payment3 decimal(20,2),
payment4 decimal(20,2),
payment5 decimal(20,2)
)
insert into PaymentData (id, payment1, payment2, payment3, payment4, payment5)
select 1 as id, 1001.00 as payment1, 1002.00 as payment2, 1003.00 as payment3, 1004.00 as payment4, 1005.00 as payment5 union all
select 2 as id, 2001.00 as payment1, 2002.00 as payment2, 2003.00 as payment3, 2004.00 as payment4, 2005.00 as payment5 union all
select 3 as id, 3001.00 as payment1, 3002.00 as payment2, 3003.00 as payment3, 3004.00 as payment4, 3005.00 as payment5 union all
select 4 as id, 4001.00 as payment1, 4002.00 as payment2, 4003.00 as payment3, 4004.00 as payment4, 4005.00 as payment5 union all
select 5 as id, 5001.00 as payment1, 5002.00 as payment2, 5003.00 as payment3, 5004.00 as payment4, 5005.00 as payment5
select * from PaymentData
if exists (select 1 from sys.objects o where o.[object_id] = object_id(N'PaymentDataConfig'))
begin
drop table PaymentDataConfig
end
create table PaymentDataConfig
(
id int,
configColumn varchar(1000)
)
insert into PaymentDataConfig (id, configColumn)
select 1 as id, 'payment1' as configColumn union all
select 2 as id, 'payment2' as configColumn union all
select 3 as id, 'payment3' as configColumn union all
select 4 as id, 'payment4' as configColumn union all
select 5 as id, 'payment5' as configColumn
select * from PaymentDataConfig
select p.*, c.*
from PaymentData p
join PaymentDataConfig c on p.id = c.id
如果我在id上连接两个表,我将得到如下结果
id payment1| payment2|payment3 |payment4| payment5|id |configColumn
------------+---------+---------+--------+----------+---+-------------
1 1001.00 | 1002.00 | 1003.00 | 1004.00| 1005.00 |1 |payment1
2 2001.00 | 2002.00 | 2003.00 | 2004.00| 2005.00 |2 |payment2
3 3001.00 | 3002.00 | 3003.00 | 3004.00| 3005.00 |3 |payment3
4 4001.00 | 4002.00 | 4003.00 | 4004.00| 4005.00 |4 |payment4
5 5001.00 | 5002.00 | 5003.00 | 5004.00| 5005.00 |5 |payment5
预期结果如下所示,在列名中,我希望看到相应的值
id payment1| payment2|payment3 |payment4| payment5|id |configColumn|correspondingValue
============|=========|=========|========|==========|===|============|==================
1 1001.00 | 1002.00 | 1003.00 | 1004.00| 1005.00 |1 |payment1 |1001.00
2 2001.00 | 2002.00 | 2003.00 | 2004.00| 2005.00 |2 |payment2 |2002.00
3 3001.00 | 3002.00 | 3003.00 | 3004.00| 3005.00 |3 |payment3 |3003.00
4 4001.00 | 4002.00 | 4003.00 | 4004.00| 4005.00 |4 |payment4 |4004.00
5 5001.00 | 5002.00 | 5003.00 | 5004.00| 5005.00 |5 |payment5 |5005.00
您可以使用CASE表达式来实现这一点:
select p.*, c.*, CASE c.configColumn WHEN N'payment1' THEN p.payment1 WHEN N'payment2' THEN p.payment2 WHEN N'payment3' THEN p.payment3 WHEN N'payment4' THEN p.payment4 WHEN N'payment5' THEN p.payment5 ELSE NULL END AS correspondingValue
from PaymentData p
join PaymentDataConfig c
on p.id = c.id
正如您的更新所提到的,如果您有许多已配置的列,则可以使用动态sql:
DECLARE @SQL nvarchar(max)=N''
DECLARE @ID int;
SELECT @ID=MIN(ID) FROM PaymentDataConfig;
WHILE @ID IS NOT NULL
BEGIN
SET @SQL=@SQL+' WHEN N''payment''+CAST(@ID AS nvarchar(20)) +N' THEN p.payment'+ CAST(@ID AS nvarchar(20))';
SELECT @ID=MIN(ID) FROM PaymentDataConfig WHERE ID>@ID;
END
SET @SQL=@SQL+N'
select p.*, c.*, CASE c.configColumn '+ @SQL + N' ELSE NULL END AS correspondingValue
from PaymentData p
join PaymentDataConfig c
on p.id = c.id'
exec sp_executesql @SQL;
您可以使用CASE表达式来实现这一点:
select p.*, c.*, CASE c.configColumn WHEN N'payment1' THEN p.payment1 WHEN N'payment2' THEN p.payment2 WHEN N'payment3' THEN p.payment3 WHEN N'payment4' THEN p.payment4 WHEN N'payment5' THEN p.payment5 ELSE NULL END AS correspondingValue
from PaymentData p
join PaymentDataConfig c
on p.id = c.id
正如您的更新所提到的,如果您有许多已配置的列,则可以使用动态sql:
DECLARE @SQL nvarchar(max)=N''
DECLARE @ID int;
SELECT @ID=MIN(ID) FROM PaymentDataConfig;
WHILE @ID IS NOT NULL
BEGIN
SET @SQL=@SQL+' WHEN N''payment''+CAST(@ID AS nvarchar(20)) +N' THEN p.payment'+ CAST(@ID AS nvarchar(20))';
SELECT @ID=MIN(ID) FROM PaymentDataConfig WHERE ID>@ID;
END
SET @SQL=@SQL+N'
select p.*, c.*, CASE c.configColumn '+ @SQL + N' ELSE NULL END AS correspondingValue
from PaymentData p
join PaymentDataConfig c
on p.id = c.id'
exec sp_executesql @SQL;
在上面的示例中,我只显示了五个付款列,但在PaymentData表中有60个这样的列。此表包含500-1000万条记录的值。是否可以标记SQL Server版本?根据请求添加了版本号在上述示例中,我只显示了五个付款列,但表PaymentData中有60个这样的列。此表包含500-1000万条记录范围内的值。是否可以标记SQL Server版本?将版本号添加为requestedI有60个这样的列,像前面提到的那样编写将非常麻烦。动态SQL是一个很好的选项,请注意,您必须启用它,默认情况下它处于关闭状态(并且具有一些安全隐患)。如果您可以重构数据,另一种方法是以4列格式存储数据,这样每个“记录”就有60行,一行ID、PaymentID、PaymentType(Payment1、Payment2等),最后是实际付款。然后查找与配置匹配的付款就在payment.PaymentID=Config.PaymentID和payment.PaymentType=Config.PaymentType之间。您可以使用Pivot或使用矩阵格式报表在SSRS中重建表样式的输出。我有60个这样的列,像前面提到的那样编写会很麻烦。动态SQL是一个很好的选择,请注意您必须启用它,默认情况下它是关闭的(并且有一些安全隐患)。如果您可以重构数据,另一种方法是以4列格式存储数据,这样每个“记录”就有60行,一行ID、PaymentID、PaymentType(Payment1、Payment2等),最后是实际付款。然后查找与配置匹配的付款就在payment.PaymentID=Config.PaymentID和payment.PaymentType=Config.PaymentType之间。您可以使用Pivot或使用矩阵格式报告在SSRS中重建表样式输出。