代码之家  ›  专栏  ›  技术社区  ›  quango

如果存在重复项,则从SQL表中删除;如果重复项超过30天,则从中删除

  •  0
  • quango  · 技术社区  · 1 年前

    我正在尝试编写一个SQL查询来访问Microsoft SQL表。我希望实现的是,我可以找到所有具有重复项的行,并且只有在重复项超过30天时才能删除它们。以下是一个示例表:

        INSERT INTO [dbo].[test]
        (id1, id2, firstName, lastName, dayTime) 
    VALUES
        (12, 13, 'Syed','Abbas','05-02-2023'),
        (12, 13, 'Syed','Abbas','07-02-2023'),
        (12, 14, 'Adam', 'Johnson', '07-02-2023'),
        (10, 9, 'Monique', 'Brown', '03-03-2023')
    

    以下是我为我的查询所写的内容:

        DELETE T
    FROM
    (
    SELECT *
    , DupRank = ROW_NUMBER() OVER (
                  PARTITION BY id1, id2
                  ORDER BY (SELECT NULL)
                )
    FROM [dbo].[test]
    ) AS T
    WHERE DupRank > 1 and dayTime < DATEADD(day, -30, GETDATE()) 
    

    我的结局 尝试 要得到的是,只有第1行(12,13,Syed,Abbas,05-02-2023)将被删除,其余值将保留。但是,当我运行这个查询时,它不会删除任何内容——没有错误,只影响了0行。

    我已经尝试了查询的单独部分,它们运行良好(即,当我只是删除重复项时,它会删除第2行,当我只删除超过30天的内容时,它将删除第1行和第4行)。我不确定我是否错误地使用了“and”子句?

    1 回复  |  直到 1 年前
        1
  •  1
  •   Charlieface    1 年前

    我猜测(尽管很难说没有看到查询计划) ORDER BY 正在引发问题。

    当你写作时 ORDER BY (SELECT NULL) 这意味着服务器可以自由地按任何顺序计算行号。所以可能是 更老的 行编号为1,较新的行编号为2。然后当你过滤到 DupRank > 1 and dayTime < DATEADD(day, -30, GETDATE()) 您正在过滤掉这两行。

    所以只需要使用确定性编号。这里合乎逻辑的做法是从最新到最旧进行编号,这样你就可以始终保留最新的一行和任何其他不到30天的行。

    DELETE T
    FROM
    (
        SELECT *,
          DupRank = ROW_NUMBER() OVER (
                    PARTITION BY T.id1, T.id2
                    ORDER BY T.dayTime DESC)
        FROM dbo.test T
    ) AS T
    WHERE T.DupRank > 1
      AND T.dayTime < DATEADD(day, -30, GETDATE());