2012-04-16 92 views
1

我正在嘗試解決t-sql練習 我需要使用id加入來更新第二個表的值。如果我不能參加,然後使用值從默認的ID(默認ID是空的Id)有趣的t-sql練習

請運行它,看看

declare @t as table (
    [id] INT 
    ,val int 
) 

insert into @t values (null, null) 
insert into @t values (2, null) 
insert into @t values (3, null) 
insert into @t values (4, null) 

declare @t2 as table (
    [id] INT 
    ,val int 
) 

insert into @t2 values (null, 11) 
insert into @t2 values (2, 22) 
insert into @t2 values (3, 33) 


select * from @t 
select * from @t2 

update t 
set t.val = t2.val 
from @t as t join @t2 as t2 
    on t.id = t2.id 
     or 
     (
      (t.id is null or t.id not in (select id from @t2)) 
      and t2.id is null 
     ) 




select * from @t 

這裏是導致它

[email protected] 
id  val 
--------------- 
NULL NULL 
2  NULL 
3  NULL 
4  NULL 

[email protected] 
id  val 
--------------- 
NULL 11 
2  22 
3  33 

[email protected] after update 
id  val 
--------------- 
NULL 11 
2  22 
3  33 
4  NULL 

如何使最後一行中的val等於11?

4  11 
+0

你說的默認的'val'是具有空'id'的行? – dotjoe 2012-04-16 21:22:00

回答

2

嘗試一下本作的更新...

update t 
set t.val = t2.val 
from @t as t join @t2 as t2 
    on t.id = t2.id 
     or 
     (
      (t.id is null or not exists (select * from @t2 where id = t.id)) 
      and t2.id is null 
     ) 

問題是not in運營商和null值。這也可以...

update t 
set t.val = t2.val 
from @t as t join @t2 as t2 
    on t.id = t2.id 
     or 
     (
      (t.id is null or t.id not in (select id from @t2 where id is not null)) 
      and t2.id is null 
     ) 
+0

我喜歡你的解決方案比我的更好,因爲它們不需要左連接或合併。我真的很驚訝'和t2.id爲null'在'INNER JOIN'中工作。 – 2012-04-16 21:43:16

+0

哈哈,說實話,如果我正在編寫查詢,我只是將默認值拖入一個變量或做額外的外連接。我不喜歡加入空值! – dotjoe 2012-04-16 21:45:21

3

該解決方案將t2連接到t2兩次,然後進行合併。

第二次連接的ON與連接上失敗的記錄匹配,然後查找「默認」大小寫。

UPDATE t 
set t.val = COALESCE(t2.val,t3.val) 
from @t as t 
    LEFT join @t2 as t2 
    on t.id = t2.id 
    LEFT JOIN @t2 t3 
    ON t2.id is null and t3.id is null 

See it working here

+0

謝謝你的一個很好的例子。對於同一張表,雙左連接是我需要深入挖掘的內容。我選擇了dotjoe的版本,因爲它顯示瞭如何解決我的鱈魚問題 – Cherven 2012-04-17 13:46:55

1

這是一種可能有用的技術。

開始用一種簡單的代碼,你想被寫:

MERGE INTO @t AS target 
    USING source 
     ON target.id = source.id 
WHEN MATCHED THEN 
    UPDATE 
     SET val = source.val; 

然後寫滿足要求的表表達式(source)。

要求1:

「由ID接合」 - 簡單存在量化例如

SELECT id, val 
    FROM @t2 AS T2 
WHERE id IN (SELECT id FROM @t) 

要求2:「如果我不能參加,然後使用值從默認的ID(默認ID是空的ID)」

- 先找到目標的id值不存在於源:

SELECT id 
    FROM @t 
EXCEPT 
SELECT id 
    FROM @t2 

然後過與來自源的行其中Id是空連接的結果:

SELECT DT1.id, T2.val 
    FROM (SELECT id 
      FROM @t 
     EXCEPT 
     SELECT id 
      FROM @t2) AS DT1, 
     @t2 AS T2 
WHERE T2.id IS NULL 

此時您需要查詢一些測試數據以確保每個查詢都滿足其各自的要求。

聯盟以上兩個結果,形成一個單一的表表達式:

SELECT id, val 
    FROM @t2 AS T2 
WHERE id IN (SELECT id 
       FROM @t)    
UNION 
SELECT DT1.id, T2.val 
    FROM (SELECT id 
      FROM @t 
     EXCEPT 
     SELECT id 
      FROM @t2) AS DT1, 
     @t2 AS T2 
WHERE T2.id IS NULL 

然後表表達式插入MERGE樣板代碼:

WITH source 
    AS 
    (
     SELECT id, val 
     FROM @t2 AS T2 
     WHERE id IN (SELECT id 
         FROM @t)    
     UNION 
     SELECT DT1.id, T2.val 
     FROM (SELECT id 
       FROM @t 
       EXCEPT 
       SELECT id 
       FROM @t2) AS DT1, 
      @t2 AS T2 
     WHERE T2.id IS NULL 
    ) 
MERGE INTO @t AS target 
    USING source 
     ON target.id = source.id 
WHEN MATCHED THEN 
    UPDATE 
     SET val = source.val;