2013-05-10 60 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