更高效的更新查询(MS SQL Server 2008)

更高效的更新查询(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小提琴 表 +---------+-----------+--------

我正试图用表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