2013-05-10 66 views
0

我有一張需要根據天氣預報進行每小時更新的表。創建表和合並的效果很好,現在我一直在使用它們。SQL Server根據參數刪除不在源代碼中的行

CREATE TABLE #WeatherHourly([Pk_Id][int], 
          [ObservationDateTime] [datetime],  
          [EffectiveDateTime] [datetime], 
          [Value] [decimal](18, 4) 
          ) 

MERGE INTO WeatherHourly AS TARGET 
USING #WeatherHourly AS Source ON Target.Pk_Id = Source.Pk_Id 
           AND Target.EffectiveDateTime = Source.EffectiveDateTime 
WHEN MATCHED THEN 
    UPDATE SET Target.Value = Source.Value, 
       Target.ObservationDateTime = Source.ObservationDateTime 
WHEN NOT MATCHED BY TARGET THEN 
    INSERT ([Pk_Id], [ObservationDateTime], [EffectiveDateTime], [Value]) 
    VALUES (Source.Pk_Id, Source.ObservationDateTime, Source.EffectiveDateTime, Source.Value); 

但我注意到有時候新的預測不包括我已經寫到表格中的舊數據。這意味着一些數據會被粘貼,因爲在合併語句中沒有寫入/更新它。這個數據實際上是無效的,因爲它沒有包含在最新的預測中。現在只需在合併中添加「不匹配的源代碼」即可,但它會刪除歷史記錄的所有行。由於其他原因,我保留了歷史記錄,無法刪除舊行,但只能刪除WeatherHourly表中仍然相關的行((從昨天到任何未來日期範圍內的EffectiveDateTime)。下面的代碼是我到目前爲止所嘗試的,但它會刪除所有不想刪除的歷史記錄行。

Delete from WeatherHourly from WeatherHourly tRow 
left JOIN #WeatherHourly t2 ON tRow.EffectiveDateTime = t2.EffectiveDateTime and tRow.Pk_Id = t2.Pk_Id 
where t2.PK_Id is null 

任何幫助,將不勝感激。

編輯爲我的新方法: 我想知道如何使用更好的選擇爲我的原始合併,使目標更多我想要的。

WITH t2 
AS 
(
SELECT * 
FROM WeatherHourly t 
WHERE EXISTS 
(
SELECT * FROM #WeatherHourly r WHERE t.EffectiveDateTime = r.EffectiveDateTime AND t.Pk_Id = r.Pk_Id 
) 
) 
MERGE t2 
AS Target 
USING #WeatherHourly 
AS Source 
ON Target.Pk_Id = Source.Pk_Id 
    AND Target.EffectiveDateTime = Source.EffectiveDateTime 
WHEN MATCHED THEN 
    UPDATE SET Target.Value = Source.Value,Target.ObservationDateTime = Source.ObservationDateTime 
WHEN NOT MATCHED BY TARGET THEN 
    INSERT ([Pk_Id],[ObservationDateTime],[EffectiveDateTime],[Value]) 
    VALUES (SourcePk_Id,Source.ObservationDateTime,Source.EffectiveDateTime,Source.Value) 
WHEN NOT MATCHED BY SOURCE THEN 
    DELETE; 

這似乎是在做我想要的。任何批評都會有所幫助。很抱歉,任何人要解決這個代碼搞砸了。

+2

請考慮NOT EXISTS模式。 MERGE可能會有問題,因爲有十多個未解決的錯誤(不必介意,編寫和理解的語法非常麻煩,並且不會向您購買您可能期望的併發控制 - 除非您添加主動提示),並且LEFT JOIN方法非常緩慢。 – 2013-05-10 20:59:14

回答

1
WITH t2 
AS 
(
SELECT * FROM WeatherHourly t 
WHERE EXISTS 
(
SELECT * FROM #WeatherHourly r WHERE t.EffectiveDateTime = r.EffectiveDateTime AND t.Pk_Id = r.Pk_Id 
) 
) 
MERGE t2 
AS Target 
USING #WeatherHourly 
AS Source 
ON Target.Pk_Id = Source.Pk_Id 
    AND Target.EffectiveDateTime = Source.EffectiveDateTime 
WHEN MATCHED THEN 
    UPDATE SET Target.Value = Source.Value,Target.ObservationDateTime = Source.ObservationDateTime 
WHEN NOT MATCHED BY TARGET THEN 
    INSERT ([Pk_Id],[ObservationDateTime],[EffectiveDateTime],[Value]) 
    VALUES (SourcePk_Id,Source.ObservationDateTime,Source.EffectiveDateTime,Source.Value) 
WHEN NOT MATCHED BY SOURCE THEN 
    DELETE; 

測試之後似乎運作良好。

0

爲什麼不刪除預先存在的EffectiveDateTime,然後插入新的?

DELETE FROM WeatherHourly 
WHERE EffectiveDateTime = (SELECT TOP(1) 
            EffectiveDateTime 
           FROM 
            #WeatherHourly) 


INSERT INTO WeatherHourly 
(
    [Pk_Id] 
    ,[ObservationDateTime] 
    ,[EffectiveDateTime] 
    ,[Value] 
) 
SELECT 
    [Pk_Id] 
    ,[ObservationDateTime] 
    ,[EffectiveDateTime] 
    ,[Value] 
FROM 
    #WeatherHourly 
+2

爲什麼要在這裏添加NOLOCK?請不要成爲那些將NOLOCK放在每個SELECT上的人之一。這可能是真的,真的是壞消息。 – 2013-05-10 21:16:20

+0

這是我工作所需要的,並且不知道更好。從我的答案中刪除。 – Jim 2013-05-10 21:18:35

+0

希望你不要在銀行工作(或準確性甚至接近重要的地方)。 – 2013-05-10 21:22:46