如何在按另一个表的列进行分区时,使用CTE删除重复的行?

时间:2014-12-24 12:53:53

标签: sql sql-server

我正在尝试使用this solution从数据库表中删除重复的行。但是,在我的情况下,是否将两行视为“重复”,必须检查另一个表。我的场景的完整副本将是这样的:

-- Foreign key between these tables as well as "Group" table omitted for simplicity...
DECLARE @ItemType TABLE(Id INT, Title NVARCHAR(50), GroupId INT);
DECLARE @Item TABLE(Id INT IDENTITY(1,1), ItemTypeId INT, Created DATETIME2);

INSERT INTO @ItemType (Id, Title, GroupId) 
VALUES  (1, 'apple', 1), (2, 'banana', 1), (3, 'beans', 2);

INSERT INTO @Item (ItemTypeId, Created) 
VALUES  (1, '20141201'), (2, '20140615'), (3, '20140614');
-- Note: Id's are generated automatically

WITH cte AS (
    SELECT ROW_NUMBER() OVER (PARTITION BY GroupId ORDER BY Created) AS Rnk
    FROM   @Item AS i
           JOIN @ItemType AS it ON i.ItemTypeId = it.Id
)
DELETE FROM cte 
WHERE Rnk > 1;

这显然会失败,并显示以下消息:

  

视图或函数'cte'不可更新,因为修改会影响多个基表。

这可以在坚持优雅的cte解决方案的同时解决吗?或者这是否需要转移到基于DELETE甚至MERGE INTO的版本?

1 个答案:

答案 0 :(得分:2)

您可以坚持使用CTE版本,但DELETE必须更明确地说明要删除哪些行。只需从CTE传递@Item.Id并根据以下内容过滤为删除的行:

WITH cte AS (
    SELECT i.Id,
           ROW_NUMBER() OVER (PARTITION BY GroupId ORDER BY Created) AS Rnk
    FROM   @Item AS i
           JOIN @ItemType AS it ON i.ItemTypeId = it.Id
)
DELETE FROM @Item
WHERE Id IN (SELECT Id FROM cte WHERE Rnk > 1);