SQL UPDATE具有复合匹配值的自联接

时间:2014-04-02 23:46:29

标签: sql-server sql-update multiple-columns self-join

我有一个包含行的MSSQL表,其中一些我需要更新,具体取决于同一个表中是否存在其他行。表格和示例数据如下所示:

SQL表:

    TABLE tblConnector(
      ID1 [int] NOT NULL,
      ID2 [int] NOT NULL,
      ID3 [int] NOT NULL,
      ...other cols...)

具有由ID1,ID2和ID3组成的PRIMARY KEY CLUSTERED - 意味着复合键必须是唯一的。

数据结构:

ID1  ID2  ID3

111  222  1
111  222  9999
333  444  1    <--- update only this row
555  666  1        
555  666  9999
777  888  2
777  888  9999 
123  456  3    <--- don't update this row

我需要更新此表中的任何行,设置ID3 = 9999,其中ID3当前为1,表中没有其他行具有相同的ID1和ID2值,ID3 = 9999。

在我的示例数据中,我只想更新第3行,设置ID3 = 9999 - 因为它有ID3 = 1并且表中没有其他行具有相同的ID1和ID2值(其中ID3&lt;&gt; ; 1)。我不想更新最后一行 - 所以使用count()来表示isolte行不是一种有效的方法。

我已尝试过多次尝试将表连接到自身,但我似乎无法获得只会影响我想要的行的UPDATE语句。

有关如何编写此SQL代码的任何建议吗?

更新:我应该更清楚 - 如果ID3中的当前值为1,我想将ID3列更新为9999 ...并且没有其他具有相同ID1和ID2值且ID3 = 9999的行.ID1,ID2和ID3包含唯一键,ID3中的设置9999不能复制已存在的键值。

3 个答案:

答案 0 :(得分:1)

按照您的确切措辞,以下内容应该有效:

UPDATE tblConnector t1
SET ID3 = 9999
WHERE NOT EXISTS
(
    SELECT 1
    FROM tblConnector t2
    WHERE t2.ID1 = t1.ID1
    AND t2.ID2 = t1.ID2
    AND t2.ID3 <> 9999
)

答案 1 :(得分:1)

也许我的阅读方式不同。

;WITH cte AS (
  SELECT ID1, ID2
    FROM tblConnector
   GROUP BY ID1, ID2
  HAVING COUNT(1) = 1
)
UPDATE tblConnector 
   SET ID3 = 9999
  FROM tblConnector a
       INNER JOIN
       cte b ON a.ID1 = b.ID1
            AND a.ID2 = b.ID2

sqlfiddle

编辑(评论后)

在UPDATE中添加了新的示例记录和WHERE ID3 = 1。在这种情况下,1是占位符,表示您要插入的任何单个值。

;WITH cte AS (
  SELECT ID1, ID2
    FROM tblConnector
   GROUP BY ID1, ID2
  HAVING COUNT(1) = 1
)
UPDATE tblConnector 
   SET ID3 = 9999
  FROM tblConnector a
       INNER JOIN
       cte b ON a.ID1 = b.ID1
            AND a.ID2 = b.ID2
 WHERE ID3 = 1

New fiddle

答案 2 :(得分:1)

没有EXISTS,没有CTE方法。我不知道这是否最有效。

update t1
set t1.id3 = 9999 
--select *
from
tblConnector as t1 
left join
(
select id1, id2, COUNT(id1) as Rowz
from tblConnector as t2
group by id1, id2
) as src
on t1.id1 = src.id1
where Rowz = 1