2013-03-06 51 views
5

數據我需要在SQL Server 2012程序執行以下僞邏輯,基於一個表變量和一個表聲明爲這樣:刪除「等效」從兩個表

​​
  1. 對於每一行在表變量數據的@tmp
  2. Table1刪除行,其中UserID/SgsID組合在Table1
  3. 匹配UserID/SgsID刪除那些UserID/SgsID共從@tmp mbinations已經從Table1

我一直在研究不同的方法,如使用OUTPUT INTOINTERSECT刪除,但不能寫在兩個表中刪除(其實查詢我不認爲這是甚至可能)。

我已經通過使用下面的代碼實現了上述步驟,但是,我想知道是否有任何T-SQL pro可能能夠提出更簡潔/高效的方法?

SQLFiddle for online version

CREATE TABLE #Table1 
    (
    ID int IDENTITY(1,1), 
    UserID int NOT NULL, 
    SgsID int NOT NULL 
    ) 

INSERT INTO #Table1 (UserID, SgsID) VALUES (5, 99) 
INSERT INTO #Table1 (UserID, SgsID) VALUES (10, 89) 
INSERT INTO #Table1 (UserID, SgsID) VALUES (150, 79) 
INSERT INTO #Table1 (UserID, SgsID) VALUES (200, 69) 
INSERT INTO #Table1 (UserID, SgsID) VALUES (250, 59) 
SELECT * FROM #Table1 

DECLARE @tmp TABLE 
    (
    ID int IDENTITY(1,1), 
    UserID int NOT NULL, 
    SgsID int NOT NULL 
    ) 

INSERT INTO @tmp (UserID, SgsID) VALUES (150, 79) 
INSERT INTO @tmp (UserID, SgsID) VALUES (200, 69) 
INSERT INTO @tmp (UserID, SgsID) VALUES (250, 59) 
INSERT INTO @tmp (UserID, SgsID) VALUES (999, 49) 
SELECT * FROM @tmp 

DECLARE @tbl_commonRows TABLE (UserID int, SgsID int) 
INSERT INTO @tbl_commonRows 
    (
    UserID, 
    SgsID 
    ) 
SELECT 
    UserID, 
    SgsID 
FROM 
    #Table1 
INTERSECT 
SELECT 
    UserID, 
    SgsID 
FROM 
    @tmp 

DELETE FROM 
    #Table1 
WHERE 
    (ID IN (
     SELECT 
      ID 
     FROM 
      #Table1 t1 INNER JOIN 
      @tbl_commonRows c ON c.UserID = t1.UserID AND c.SgsID = t1.SgsID)) 

DELETE FROM 
    @tmp 
WHERE 
    (ID IN (
     SELECT 
      ID 
     FROM 
      @tmp t2 INNER JOIN 
      @tbl_commonrows c ON c.UserID = t2.UserID AND c.SgsID = t2.SgsID)) 

SELECT * FROM #Table1 
SELECT * FROM @tmp 
DROP TABLE #Table1 

回答

1

你有看着使用合併這個?可能是另一種選擇,語法很好,易於遵循。

MERGE (Transact-SQL)

+0

你能否舉一個例子來說明如何使用它?我認爲,因爲MERGE基於源表對目標表進行操作,因此在這裏不適用,因爲我們在源表和目標表上操作......? – EvilDr 2013-03-07 09:09:19

+0

您可以通過使用output子句修改源表來擴展合併:http://stackoverflow.com/questions/7331725/how-to-delete-from-source-using-merge-command-in-sql- server-2008 – steoleary 2013-03-07 10:35:54

+0

今天早上和MERGE一起玩過 - 我絕對喜歡它。多麼驚人的加法。與輸出合併是非常好的:-) – EvilDr 2013-03-08 11:48:17

4

這裏的解決方案:

DECLARE @tmp_ids TABLE (
    id1 INT, 
    id2 INT 
) 

INSERT INTO @tmp_ids (id1, id2) 
SELECT 
    t1.id, 
    t2.id 
FROM Table1 t1 
INNER JOIN tmp t2 
    on (t1.UserID = t2.UserID AND t1.SgsID = t2.SgsID) 

DELETE FROM Table1 
WHERE id IN (SELECT id1 FROM @tmp_ids) 

DELETE FROM tmp 
WHERE id IN (SELECT id2 FROM @tmp_ids) 

請記住 - 我創建物理表tmp和表1

+0

我喜歡的感謝,多比我的嘗試更簡潔...! – EvilDr 2013-03-06 12:30:26

+0

它無法正常工作。例如,如果'@ tmp'表中有'(250,100)'和'(250,59)'的記錄,'#Table1'中有'(250,59)'。兩個記錄都將從'@ tmp'中刪除,但'#Table1'只匹配'(250,29)',應該從'@ tmp'中刪除。 – 2013-03-06 12:51:39

+0

@IvanG你錯了,它工作得很好。嘗試一下:) – Sergio 2013-03-06 12:54:29

2

你可以採取的事實,即輸出指令可以採取比INSERTED越來越被刪列的刪除(但不插入,黯然)優勢:

DECLARE @output TABLE (id int) 

    DELETE FROM tbl 
    OUTPUT tmp.ID INTO @output(id) 
    FROM #Table1 tbl 
    JOIN @tmp tmp 
     ON tbl.UserID = tmp.UserID 
     AND tbl.SgsID = tmp.SgsID 

    DELETE FROM tmp 
    FROM @tmp tmp 
    JOIN @Output outp ON tmp.id = outp.id 
+0

這是我希望沒有人張貼時,當我遇到你的答案。 :) 好一個。 – 2013-03-06 20:19:32

+0

不知道那個,謝謝。但是ID列在兩個表中可能都不相同,因爲在UserID/sgsID中可能沒有跨表的相同ID。請問您的代碼在這種情況下仍然相關嗎? – EvilDr 2013-03-07 09:00:01

+1

@EvilDr是的;這實際上是一個想輸出tmp.ID的理由,所以你知道當你刪除它時,你會回到tmp中相應的行。 – 2013-03-07 14:55:38