删除旧记录,同时保持每个父项的最小记录数

时间:2012-02-10 08:38:56

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

我的问题类似于sql statement to delete records older than XXX as long as there are more than YY rows,但这个问题只涉及单亲,我想一次性删除所有父母的记录。

考虑下表:

CREATE TABLE Children
(
    ChildId int NOT NULL,
    ChildCreated datetime NOT NULL,
    ParentId int NOT NULL
) 

这可以是任何父子关系,因此名称是通用的。

我想删除所有超过一个月的孩子,但无论年龄大小,都需要为每位家长保留最少数量的孩子。

我用嵌套的SELECT和GROUP BYs尝试了一些语句,它给了我一些结果,但没有给我正确的结果集。

因为我使用的是SQL Server,所以我提出了以下解决方案:

WITH CTE AS
(
  SELECT ROW_NUMBER() OVER (Partition BY ParentId ORDER BY ChildCreated DESC) 
  As RowNo, ChildCreated FROM Children
)

DELETE FROM CTE WHERE RowNo > 10
AND RevisionCreated < DATEADD(MONTH,-1,GetDate())

公用表表达式将每个父项的所有子项组合在一起,并根据创建顺序添加连续的行号。每个父母的最新孩子都有 行号为1,第十行最新为10.所以我可以删除所有记录 只要他们还超过一个月,他们的数字就会增加10个。

我的问题是,如果我不得不在不支持CTE的系统上做同样的事情,该怎么办?这个问题的 ANSI SQL-92 解决方案是什么?

2 个答案:

答案 0 :(得分:2)

很可能拖累表现,但遵循声明

  • 添加rownumber,为每个组重新启动,对同一组的子项数量的每条记录使用子选择。
  • 返回一个内存表,其中包含给定rownumber的ChildId
  • JOIN返回ChildId
  • 上的原始表格
  • 添加了WHERE子句,您可以在其中过滤rownumber中的Children和/或其他列。
  • DELETE FROM声明中使用结果。

SQL声明

DELETE FROM Children
FROM    Children c
        INNER JOIN (
          SELECT  ChildId
                  , ( SELECT COUNT(*) + 1
                      FROM   Children rn
                      WHERE  rn.ChildCreated < Children.ChildCreated
                             AND rn.ChildId = Children.ParentId
                      ) AS rn           
          FROM    Children
        ) rn ON rn.ChildId = c.ChildId          
WHERE   rn.rn > 10
        AND ChildCreated < DATEADD(MONTH,-1,GetDate())

答案 1 :(得分:2)

基于其他响应,以及我的查询相对简单,我想我可能过度简化了问题,但我假设,因为parentID不可为空,它不引用childID,在这种情况下,它可以简单地实现如下所示

DELETE  Children
FROM    Children a
WHERE   ChildCreated < DATEADD(MONTH, -1, GETDATE())
AND     (   SELECT  COUNT(*)    -- NUMBER OF NEWER CHILDREN WITH THE SAME PARENT
            FROM    Children b
            WHERE   a.ParentID = b.ParentID
            AND (   a.ChildCreated < b.ChildCreated
                OR  (a.ChildCreated = b.ChildCreated AND a.ChildID > b.ChildID)
                )
        ) >= 10

虽然这个确切的SQL可能需要根据RDBMS进行调整,但我不知道任何无法应用此主体的RDBMS。