将 Table A 中的列匹配到 Table B 中的行值以更新 Table B 中的另一列
Match Columns in Table A to Row Values in Table B to update another Column in Table B
我想将 TableA 的列与 TableB 的一列中的值匹配,以便更新 TableB 中另一列中的值。
表A:
001100
001200
003000
004000
005000
1
0
1
1
0
表B:
Column_1
Score
001100
001200
003000
004000
005000
因此,例如,我希望将 TableB 中的“得分”列更新为 001100 的值“1”。因此结果 table 应如下所示:
Column_1
Score
001100
1
001200
0
003000
1
004000
1
005000
0
我知道如何通过硬编码和一次一行更新它:
Update [TableB]
Set Score = [001100]
From [Table A]
Where [Column_1] = '001100'
但是我有超过 50 个这样的专栏,所以如果有人可以建议我如何在不必对列名称进行硬编码的情况下完成这项工作,那就太好了。因此,一个代码将从 TableA 中动态获取列的名称,然后将其与 tableB Column_1 值匹配。
如果您在 TableA
中的列名称是固定的并且不会更改,您可以构建一个临时 table 并针对临时 table 进行更新:
DECLARE @Scores TABLE (Column_1 varchar(20), Score int)
-- Build the data in the temporary table
INSERT @Scores (Column_1, Score)
SELECT '001100', [001100] FROM TableA
UNION ALL SELECT '001200', [001200] FROM TableA
UNION ALL SELECT '003000', [003000] FROM TableA
-- Repeat for all columns
UPDATE TableB
SET Score = s.Score
FROM TableB JOIN @Scores s ON TableB.[Column_1] = s.[Column_1]
如果TableA
中有多行,您将需要管理临时数据中的数据。换句话说,如果您的临时 table 包含 TableB
中同一行的多行,那么更新将不会像您预期的那样工作。您需要对分数进行分组和求和:
-- Build the data in the temporary table
INSERT @Scores (Column_1, Score)
SELECT '001100', SUM([001100]) FROM TableA
UNION ALL SELECT '001200', SUM([001200]) FROM TableA
UNION ALL SELECT '003000', SUM([003000]) FROM TableA
-- Repeat for all columns
这是一个例子:
-- Source data
DECLARE @TableA TABLE([001100] int, [001200] int, [003000] int, [004000] int, [005000] int);
DECLARE @TableB TABLE([Column_1] varchar(20), Score int);
INSERT @TableA ([001100], [001200], [003000], [004000], [005000])
VALUES (1, 0, 1, 1, 0);
INSERT @TableB ([Column_1])
VALUES ('001100'), ('001200'), ('003000'), ('004000'), ('005000');
-- Answer
DECLARE @Scores TABLE (Column_1 varchar(20), Score int);
INSERT @Scores (Column_1, Score)
SELECT '001100', SUM([001100]) FROM @TableA
UNION ALL SELECT '001200', SUM([001200]) FROM @TableA
UNION ALL SELECT '003000', SUM([003000]) FROM @TableA
UNION ALL SELECT '004000', SUM([004000]) FROM @TableA
UNION ALL SELECT '005000', SUM([005000]) FROM @TableA
;
UPDATE TableB
SET Score = s.Score
FROM @TableB TableB JOIN @Scores s ON TableB.[Column_1] = s.[Column_1];
SELECT * FROM @TableB;
结果如下:
Column_1
Score
001100
1
001200
0
003000
1
004000
1
005000
0
给你。
这将动态生成正确的 SQL 以从 Table A
中的值更新 Table B
中的 Score
为 任意数字 列。
唯一的要求是 Table A
中的列名称与 table B
中的 Column_1
的值匹配
首先我需要列的列表,这可以从 sys.columns
获得。
然后我使用 for xml path
.
将它们连接成一个字符串
然后我能够动态构建一个更新语句,该语句使用列列表并将它们逆透视以匹配 TableB
中的行
最后执行动态构建的SQL.
如果您在(实际)表上有合适的索引,这将是高性能的。
create table TableA ([001100] int, [001200] int, [003000] int, [004000] int [005000] int)
insert into TableA
select 1,0,1,1,0
create table TableB (Column_1 varchar(10), Score int)
insert into TableB (Column_1) select '001100'
insert into TableB (Column_1) select '001200'
insert into TableB (Column_1) select '003000'
insert into TableB (Column_1) select '004000'
insert into TableB (Column_1) select '005000'
declare @cols nvarchar(max), @sql nvarchar(max)
select @cols=Stuff((
select ', '+QuoteName(c.name )
from sys.tables t join sys.columns c on c.object_id=t.object_id
where t.[name]='TableA'
for xml path(''), type
).value('.[1]', 'varchar(100)'), 1, 2, ''
)
set @sql='
update b set
b.score=p.val
from (
select ' + @cols + '
from TableA -- where clause if relevant
) s
unpivot (
val for col in (' + @cols + ')
) p
join TableB b on b.Column_1=p.col'
exec(@sql)
我想将 TableA 的列与 TableB 的一列中的值匹配,以便更新 TableB 中另一列中的值。
表A:
001100 | 001200 | 003000 | 004000 | 005000 |
---|---|---|---|---|
1 | 0 | 1 | 1 | 0 |
表B:
Column_1 | Score |
---|---|
001100 | |
001200 | |
003000 | |
004000 | |
005000 |
因此,例如,我希望将 TableB 中的“得分”列更新为 001100 的值“1”。因此结果 table 应如下所示:
Column_1 | Score |
---|---|
001100 | 1 |
001200 | 0 |
003000 | 1 |
004000 | 1 |
005000 | 0 |
我知道如何通过硬编码和一次一行更新它:
Update [TableB]
Set Score = [001100]
From [Table A]
Where [Column_1] = '001100'
但是我有超过 50 个这样的专栏,所以如果有人可以建议我如何在不必对列名称进行硬编码的情况下完成这项工作,那就太好了。因此,一个代码将从 TableA 中动态获取列的名称,然后将其与 tableB Column_1 值匹配。
如果您在 TableA
中的列名称是固定的并且不会更改,您可以构建一个临时 table 并针对临时 table 进行更新:
DECLARE @Scores TABLE (Column_1 varchar(20), Score int)
-- Build the data in the temporary table
INSERT @Scores (Column_1, Score)
SELECT '001100', [001100] FROM TableA
UNION ALL SELECT '001200', [001200] FROM TableA
UNION ALL SELECT '003000', [003000] FROM TableA
-- Repeat for all columns
UPDATE TableB
SET Score = s.Score
FROM TableB JOIN @Scores s ON TableB.[Column_1] = s.[Column_1]
如果TableA
中有多行,您将需要管理临时数据中的数据。换句话说,如果您的临时 table 包含 TableB
中同一行的多行,那么更新将不会像您预期的那样工作。您需要对分数进行分组和求和:
-- Build the data in the temporary table
INSERT @Scores (Column_1, Score)
SELECT '001100', SUM([001100]) FROM TableA
UNION ALL SELECT '001200', SUM([001200]) FROM TableA
UNION ALL SELECT '003000', SUM([003000]) FROM TableA
-- Repeat for all columns
这是一个例子:
-- Source data
DECLARE @TableA TABLE([001100] int, [001200] int, [003000] int, [004000] int, [005000] int);
DECLARE @TableB TABLE([Column_1] varchar(20), Score int);
INSERT @TableA ([001100], [001200], [003000], [004000], [005000])
VALUES (1, 0, 1, 1, 0);
INSERT @TableB ([Column_1])
VALUES ('001100'), ('001200'), ('003000'), ('004000'), ('005000');
-- Answer
DECLARE @Scores TABLE (Column_1 varchar(20), Score int);
INSERT @Scores (Column_1, Score)
SELECT '001100', SUM([001100]) FROM @TableA
UNION ALL SELECT '001200', SUM([001200]) FROM @TableA
UNION ALL SELECT '003000', SUM([003000]) FROM @TableA
UNION ALL SELECT '004000', SUM([004000]) FROM @TableA
UNION ALL SELECT '005000', SUM([005000]) FROM @TableA
;
UPDATE TableB
SET Score = s.Score
FROM @TableB TableB JOIN @Scores s ON TableB.[Column_1] = s.[Column_1];
SELECT * FROM @TableB;
结果如下:
Column_1 | Score |
---|---|
001100 | 1 |
001200 | 0 |
003000 | 1 |
004000 | 1 |
005000 | 0 |
给你。
这将动态生成正确的 SQL 以从 Table A
中的值更新 Table B
中的 Score
为 任意数字 列。
唯一的要求是 Table A
中的列名称与 table B
Column_1
的值匹配
首先我需要列的列表,这可以从 sys.columns
获得。
然后我使用 for xml path
.
然后我能够动态构建一个更新语句,该语句使用列列表并将它们逆透视以匹配 TableB
最后执行动态构建的SQL.
如果您在(实际)表上有合适的索引,这将是高性能的。
create table TableA ([001100] int, [001200] int, [003000] int, [004000] int [005000] int)
insert into TableA
select 1,0,1,1,0
create table TableB (Column_1 varchar(10), Score int)
insert into TableB (Column_1) select '001100'
insert into TableB (Column_1) select '001200'
insert into TableB (Column_1) select '003000'
insert into TableB (Column_1) select '004000'
insert into TableB (Column_1) select '005000'
declare @cols nvarchar(max), @sql nvarchar(max)
select @cols=Stuff((
select ', '+QuoteName(c.name )
from sys.tables t join sys.columns c on c.object_id=t.object_id
where t.[name]='TableA'
for xml path(''), type
).value('.[1]', 'varchar(100)'), 1, 2, ''
)
set @sql='
update b set
b.score=p.val
from (
select ' + @cols + '
from TableA -- where clause if relevant
) s
unpivot (
val for col in (' + @cols + ')
) p
join TableB b on b.Column_1=p.col'
exec(@sql)