2011-10-25 55 views
1

我有一個記錄表,它具有自我關係。內部連接的SQL更新

另外 - 使搜索更容易 - 我有一個確定的紀錄已被引用,因此該行現在是「過時的」,並且是唯一有審計目的的標誌:

CREATE TABLE Records 
(
    RecordID INT(5) NOT NULL, 
    Replaces INT(5) NULL, 
    Obsolete INT(1) NOT NULL 
) 

RecordID是PK,Replaces鏈接到之前被替換的RecordID,Obsolete是冗餘信息,只是說另一個記錄已經替換了這個。它只是使搜索更容易。桌子非常大。這些只是3列。

唯一的問題是:存在於系統中的查詢中的一個錯字所以對於一個小組行,所述作廢值未設置爲1(真)。

此查詢將顯示所有陳舊等於記錄爲0,這應該是等於1:

SELECT * 
    FROM Records AS rec1 
LEFT JOIN Records AS rec2 
     ON rec1.Replaces = rec2.RecordID 
    WHERE rec2.RecordID IS NOT NULL 
     AND rec2.Obsolete = 0; 

現在我需要運行一個UPDATE改變所有這些req2.Obsolete從0到1,但我不確定如何使用INNER JOIN編寫查詢。

回答

1

您不需要內部連接。由於您的查詢已經返回了需要更新的記錄,只是這樣做:

Update Records 
set Obsolete=1 where 
RecordID in (
SELECT rec2.RecordID  
     FROM Records AS rec1 
LEFT JOIN Records AS rec2 
     ON rec1.Replaces = rec2.RecordID 
    WHERE rec2.RecordID IS NOT NULL 
     AND rec2.Obsolete = 0 
) 
+0

「你不需要內部連接」 - 如果你的'LEFT OUTER JOIN'是語義上等效於'INNER JOIN'則不會,使其內部聯接? – onedaywhen

1
UPDATE Records 
SET obsolete = 1 
WHERE recordID in (
SELECT rec1.recordid 
    FROM Records AS rec1 
LEFT JOIN Records AS rec2 
     ON rec1.Replaces = rec2.RecordID 
    WHERE rec2.RecordID IS NOT NULL 
     AND rec2.Obsolete = 0 
) 
0

我會建議使用臨時表中的兩個步驟做這個:

-- Create temporary table for holding RecordIDs to be marked as obsolete 
CREATE TEMPORARY TABLE `mark_obsolete` (`RecordID` INT NOT NULL); 

-- Insert RecordIDs to mark as obsolete into temp table 
INSERT INTO `mark_obsolete` (`RecordID`) 
SELECT `rec2`.`RecordID` 
FROM 
    `Records` AS `rec1` 
    INNER JOIN `Records` AS `rec2` 
     ON `rec1`.`Replaces` = `rec2`.`RecordID` 
WHERE `rec2`.`Obsolete` = 0; 

-- Update records using inner join to temp table 
UPDATE 
    `Records` AS `r` 
    INNER JOIN `mark_obsolete` AS `o` 
     ON `r`.`RecordID` = `o`.`RecordID` 
SET `r`.`Obsolete` = 1; 

DROP TEMPORARY TABLE `mark_obsolete`; 

注意使用LEFT JOINWHERE rec2.RecordID IS NOT NULLINNER JOIN相同。

之所以使用臨時表是爲了避免更新在子查詢中使用同一個表時,鎖定問題。它也可能會給你比使用IN子句更好的性能。