我有一个具有唯一非聚集索引的表,并且此索引中列出了4个列.我想更新表中的大量行.如果我这样做,它们将不再是不同的,因此更新因索引而失败.
我想要禁用索引,然后删除最旧的重复行.到目前为止,这是我的查询:
SELECT t.itemid,t.fieldid,t.version,updated FROM dbo.VersionedFields w inner JOIN ( SELECT itemid,fieldid,version,COUNT(*) AS QTY FROM dbo.VersionedFields GROUP BY itemid,version HAVING COUNT(*) > 1 ) t on w.itemid = t.itemid and w.fieldid = t.fieldid and w.version = t.version
内部联接内部的选择返回我们想要删除的正确数量的记录,但对它们进行分组,实际上有两倍的数量.
如何才能做到这一点?
解决方法
如果你说sql(结构化查询语言),但真正意味着它是sql Server(微软关联数据库系统),如果你使用的是sql Server 2005或更新版本,你可以使用CTE(公用表表达式)来达到这个目的.
使用此CTE,您可以按照某些条件对数据进行分区 – 即ItemId(或列的组合) – 并为每个分区的sql Server编号所有行开始,按其他一些条件排序 – 即可能是版本(或其他一些专栏).
所以尝试这样的事情:
;WITH PartitionedData AS ( SELECT itemid,ROW_NUMBER() OVER(PARTITION BY ItemId ORDER BY version DESC) AS 'RowNum' FROM dbo.VersionedFields ) DELETE FROM PartitionedData WHERE RowNum > 1
基本上,您按照某些条件对数据进行分区并对每个分区进行编号,每个新分区从1开始,按其他一些条件(例如日期或版本)排序.
因此,对于数据的每个“分区”,“最新”条目具有RowNum = 1,并且属于同一分区的任何其他条目(通过具有相同的partitino值)将具有从2到多行的顺序编号值.在那个分区.
如果你只想保留最新的条目 – 删除RowNum大于1的任何东西,你就完成了!