2013-10-10 32 views
2

最大的一组我有一个表与下面的模式记录:如何删除不从SQL表

ID NVARCHAR(10) 
Message NVARCHAR(300) 
UpdateTime DATETIME 

其中ID是外键。新的邮件记录将以相同的UpdateTime添加到群集中。一个例子是(由IDUpdateTime排序):

ID | Status  | UpdateTime 
--------------------------------- 
42  Cluster1-Msg1 2012-12-25 
42  Cluster1-Msg2 2012-12-25 
42  Cluster2-Msg1 2013-10-10 
42  Cluster2-Msg2 2013-10-10 
43  Cluster4-Msg1 2011-11-27 

这里ID#42与4个消息,在两个组在不同的日期集群相关联,而ID#43仅与一个消息相关联。

有时候我希望通过清除这张表,对于每个具有相同ID的组,删除所有其组UpdateTime小于该组内最大值的消息记录。最终的结果在上面的例子是:

42  Cluster2-Msg1 2013-10-10 
42  Cluster2-Msg2 2013-10-10 
43  Cluster4-Msg1 2011-11-27 

下面的SQL查询查找所有我想要删除的记录:

SELECT Msgs.ID, Msgs.UpdateTime 
FROM Messages Msgs 
JOIN 
(SELECT ID, MAX(UpdateTime) AS MaxTime FROM Messages GROUP BY ID) MaxTimes 
ON Msgs.ID = MaxDates.ID 
WHERE Msgs.UpdateTime < MaxTimes.MaxTime 

现在,我希望写一个DELETE语句删除项匹配上面查询返回的结果。该 记录必须根据IDUpdateTime值被删除。我只是不理解如何在Transact-SQL中表达这一点。

+0

如果你有重复?你想保持两个还是只有一个? – Paparazzi

+0

将表看作包含消息组(组密钥是ID列)。我想删除任何“旧”消息,即每个组中的日期少于最大日期的消息。 –

+0

你也可以使用'ROW_NUMBER'来做到这一点。 –

回答

4
DELETE Msgs 
FROM Messages Msgs 
JOIN (SELECT ID, MAX(UpdateTime) AS MaxTime FROM Messages GROUP BY ID) MaxTimes 
    ON Msgs.ID = MaxDates.ID 
WHERE Msgs.UpdateTime < MaxTimes.MaxTime 

注意,我所做的,这是复制原始的SELECT语句,而第一行代码更改从SELECT ...DELETE Msgs。您必须指定表名,因为查询的FROM部分中有多个表表达式。

+0

就验证了这一点在我的机器上。作品一种享受。感谢您的及时答复! –

1
DELETE DUB 
FROM Messages AS DUB 
WHERE EXISTS (
      SELECT SUB.ID 
      FROM Messages AS SUB 
      WHERE SUB.ID = DUB.ID 
      GROUP BY SUB.ID 
      HAVING MAX(SUB.UpdateTime) > DUB.UpdateTime 
     ) 

我觉得这种相关的子查询更具可读性。