我的问题类似于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 解决方案是什么?
答案 0 :(得分:2)
很可能拖累表现,但遵循声明
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。