【问题标题】:SQL Server delete rows not in source based on parametersSQL Server 根据参数删除不在源中的行
【发布时间】:2013-05-05 15:19:01
【问题描述】:

我有一个表格,需要根据即将到来的天气预报每小时更新一次。创建表格和合并效果很好,我最近一直在使用它们。

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;

这似乎正在做我想要的。任何批评都会有所帮助。对不起,谁来修复这个代码搞砸了。

【问题讨论】:

  • 请考虑不存在模式。 MERGE 可能会出现问题,因为有十几个未解决的错误(不要介意语法编写和理解起来真的很麻烦,并且不会为您购买您可能期望的并发控制 - 除非您添加积极的提示),以及 LEFT JOIN方法是出了名的慢。

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


【解决方案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;

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

【讨论】:

    【解决方案2】:

    为什么不删除已有的 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
    

    【讨论】:

    • 为什么要在此处添加 NOLOCK?请不要成为将 NOLOCK 放在每个 SELECT 上的那些人之一。这可能是非常非常糟糕的消息。
    • 我工作的地方需要它,不知道更好。从我的答案中删除。
    • 希望您不要在银行(或任何对准确性非常重要的地方)工作。
    • 我不确定这是否可行,我也不完全记得我为什么要走合并路线。那是不久前的事了。当我合并时,我正在跨越几个不同的 Pk_Id 和多个 EffectiveDateTime,所有这些都具有相同的 ObservationDateTime。希望这是有道理的。
    • 没有ORDER BYTOP 应该做什么?从#WeatherHourly 中选择一个随机行并从WeatherHourly 中删除相关行?
    猜你喜欢
    • 2020-01-05
    • 1970-01-01
    • 2014-04-03
    • 2020-11-05
    • 1970-01-01
    • 2023-03-17
    • 2018-11-01
    • 2018-04-05
    • 2011-01-09
    相关资源
    最近更新 更多