SQL Server根据参数删除不在源中的行

时间:2013-05-10 20:57:33

标签: sql sql-server merge delete-row sql-delete

我有一张表需要根据天气预报每小时更新一次。创建表和合并效果很好,我现在已经使用它们了。

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);

但我注意到的是,有时新的预测不包括我已经写入表中的旧数据。这意味着一些数据仍然存在,因为没有任何数据在merge语句中写入/更新它。此数据实际上无效,因为它未包含在最新预测中。现在只需在合并中添加“不匹配的源”即可,但会删除历史记录的所有行。我目前保留历史记录是出于其他原因而不能删除旧行,但只能删除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 个答案:

答案 0 :(得分: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;

经过测试,这似乎运作良好。

答案 1 :(得分: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