更高效的更新查询(MS SQL Server 2008)
我正试图用表B中相应的ADDR_id更新下面表a中的多个列。这是一个片段,实际上我在TableA中有30个位置,在TableB中有30个EXT_ID,所以执行Update语句需要很长时间。问题是表A中的30个位置中的任何一个都可能存在于表B中的30个EXT_ID中 例如,在表a中,ID=44231,位置A35555可能与EXT_ID_27中的表B相匹配,所以我真的希望有人能提出比900条更新语句更好的替代方案 下面是SQL小提琴 表更高效的更新查询(MS SQL Server 2008),sql,sql-server,sql-server-2008,sql-update,Sql,Sql Server,Sql Server 2008,Sql Update,我正试图用表B中相应的ADDR_id更新下面表a中的多个列。这是一个片段,实际上我在TableA中有30个位置,在TableB中有30个EXT_ID,所以执行Update语句需要很长时间。问题是表A中的30个位置中的任何一个都可能存在于表B中的30个EXT_ID中 例如,在表a中,ID=44231,位置A35555可能与EXT_ID_27中的表B相匹配,所以我真的希望有人能提出比900条更新语句更好的替代方案 下面是SQL小提琴 表 +---------+-----------+--------
+---------+-----------+-------------------------------------+----------------+-------------------------------------+
| ID | LOC_1 | LOC_1_ADDR_ID | LOC_2 | LOC_2_ADDR_ID |
+---------+-----------+-------------------------------------|----------------+-------------------------------------|
| 44231 | A35555 | Trying to Populate Should Be Z76543 | B68754 | Trying to Populate should be Z45545 |
| 87563 | A36666 | Trying to Populate Should Be Z83465 | Q23548 | Trying to Populate should be Z89224 |
| 85387 | R14587 | Trying to Populate Should be Z66371 | A35555 | Trying to Populate should be Z93827 |
+---------+-----------+-------------------------------------+----------------+-------------------------------------|
表B(每个记录ID的外部ID是唯一的,但多个记录ID可以具有相同的外部ID)
谢谢你的建议 如果表B中的30列“对”实际上是具有相同含义的重复数据(一个位置键/地址对),那么设计应该只有2列包含更多数据。实际表不遵循此设计,但您可以查询数据
SELECT EXT_ID_1 AS EXT_ID, ADDR_ID_1 AS ADDR_ID FROM TableB UNION ALL
SELECT EXT_ID_2 AS EXT_ID, ADDR_ID_2 AS ADDR_ID FROM TableB UNION ALL
SELECT EXT_ID_3 AS EXT_ID, ADDR_ID_3 AS ADDR_ID FROM TableB UNION ALL
...
SELECT EXT_ID_30 AS EXT_ID, ADDR_ID_30 AS ADDR_ID FROM TableB
这将获得两列数据,更容易编写查询。将其转储到临时表(或表变量)中,您可以继续使用30条UPDATE语句,这比900条要好
或者,您可以在一条语句中尝试:
WITH (
SELECT EXT_ID_1 AS EXT_ID, ADDR_ID_1 AS ADDR_ID FROM TableB UNION ALL
SELECT EXT_ID_2 AS EXT_ID, ADDR_ID_2 AS ADDR_ID FROM TableB UNION ALL
SELECT EXT_ID_3 AS EXT_ID, ADDR_ID_3 AS ADDR_ID FROM TableB UNION ALL
...
SELECT EXT_ID_30 AS EXT_ID, ADDR_ID_30 AS ADDR_ID FROM TableB
) AS SimplifiedTableB
UPDATE TableA
SET
LOC_1_ADDR_ID = COALESCE(TableB1.ADDR_ID, LOC_1_ADDR_ID),
LOC_2_ADDR_ID = COALESCE(TableB2.ADDR_ID, LOC_2_ADDR_ID),
LOC_3_ADDR_ID = COALESCE(TableB3.ADDR_ID, LOC_3_ADDR_ID),
...
LOC_30_ADDR_ID = COALESCE(TableB30.ADDR_ID, LOC_30_ADDR_ID)
FROM
TableA
LEFT JOIN SimplifiedTableB AS TableB1 ON TableA.LOC1 = TableB1.EXT_ID
LEFT JOIN SimplifiedTableB AS TableB2 ON TableA.LOC2 = TableB2.EXT_ID
LEFT JOIN SimplifiedTableB AS TableB3 ON TableA.LOC3 = TableB3.EXT_ID
...
LEFT JOIN SimplifiedTableB AS TableB30 ON TableA.LOC30 = TableB30.EXT_ID
但是,出于正确性和性能的考虑,我建议事先测试它。注意到这一点得到了回答,因为我一直在研究这个问题,所以这里有一个替代方案。。 收到的一些信息
如果我理解正确,您需要使用表B中的相应值更新表A中的30列,并且每个连接都应该发生在不同的列上(LOC_1=EXT_ID_1更新LOC_1_ADDR_ID,LOC_2=EXT_ID_2更新LOC_2_ADR_ID,等等)?LOC u 1=EXT_ID_1到EXT_ID_30(可以是30个EXT_ID列中的匹配项)但这30个外部ID中只存在一个匹配项。我正在仔细阅读你的建议,谢谢。这很好,我需要添加REC_ID,因为EXT_ID在表中不是唯一的,但它对于每个REC_ID都是唯一的,所以这允许我确定每个REC_ID是否存在EXT_ID,并返回相关的ADDR_ID。TableB只有90k条记录,并且增长缓慢,因此即使生成一个包含~3M条记录的表,它也可以很好地用于日常工作支持的谢谢你,乔纳森!
WITH (
SELECT EXT_ID_1 AS EXT_ID, ADDR_ID_1 AS ADDR_ID FROM TableB UNION ALL
SELECT EXT_ID_2 AS EXT_ID, ADDR_ID_2 AS ADDR_ID FROM TableB UNION ALL
SELECT EXT_ID_3 AS EXT_ID, ADDR_ID_3 AS ADDR_ID FROM TableB UNION ALL
...
SELECT EXT_ID_30 AS EXT_ID, ADDR_ID_30 AS ADDR_ID FROM TableB
) AS SimplifiedTableB
UPDATE TableA
SET
LOC_1_ADDR_ID = COALESCE(TableB1.ADDR_ID, LOC_1_ADDR_ID),
LOC_2_ADDR_ID = COALESCE(TableB2.ADDR_ID, LOC_2_ADDR_ID),
LOC_3_ADDR_ID = COALESCE(TableB3.ADDR_ID, LOC_3_ADDR_ID),
...
LOC_30_ADDR_ID = COALESCE(TableB30.ADDR_ID, LOC_30_ADDR_ID)
FROM
TableA
LEFT JOIN SimplifiedTableB AS TableB1 ON TableA.LOC1 = TableB1.EXT_ID
LEFT JOIN SimplifiedTableB AS TableB2 ON TableA.LOC2 = TableB2.EXT_ID
LEFT JOIN SimplifiedTableB AS TableB3 ON TableA.LOC3 = TableB3.EXT_ID
...
LEFT JOIN SimplifiedTableB AS TableB30 ON TableA.LOC30 = TableB30.EXT_ID
select tblB.REC_ID, tblB.ADDR_ID, tblB.EXT_ID
into #tempTableB
from
(
select REC_ID, ADDR_ID, EXT_ID
from TableB
Unpivot
(
ADDR_ID for ADDR_IDS in (ADDR_ID_1, ADDR_ID_2)
) as UnPvtADDR
Unpivot
(
EXT_ID for EXT_IDS in (EXT_ID_1, EXT_ID_2)
) as UnPvtEXT
where RIGHT(ADDR_IDS, 1) = RIGHT(EXT_IDS, 1)
) tblB
-- [depend on number of records in #tmepTableB]
-- Create Index on #tempTablB.REC_ID to improve performance if required
update tblA
set LOC_1_ADDR_ID = (select ADDR_ID from #tempTableB where REC_ID = tblA.ID and EXT_ID = tblA.LOC_1)
, LOC_2_ADDR_ID = (select ADDR_ID from #tempTableB where REC_ID = tblA.ID and EXT_ID = tblA.LOC_2)
-- .. and the rest of the columns
from TableA tblA
inner join
#tempTableB tblB
on tblA.ID = tblB.REC_ID
where tblA.ID = tblB.REC_ID
select * from TableA