Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 删除非不同行_Sql_Sql Server_Greatest N Per Group - Fatal编程技术网

Sql 删除非不同行

Sql 删除非不同行,sql,sql-server,greatest-n-per-group,Sql,Sql Server,Greatest N Per Group,我有一个表,它有一个唯一的非聚集索引,该索引中列出了4列。我想更新表中的大量行。如果我这样做,它们将不再是不同的,因此更新会因为索引而失败 我想禁用索引,然后删除最旧的重复行。以下是我目前的疑问: SELECT t.itemid, t.fieldid, t.version, updated FROM dbo.VersionedFields w inner JOIN ( SELECT itemid, fieldid, version, COUNT(*) AS QTY FROM db

我有一个表,它有一个唯一的非聚集索引,该索引中列出了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, fieldid, version
    HAVING COUNT(*) > 1
) t 
on w.itemid = t.itemid and w.fieldid = t.fieldid and w.version = t.version
内部联接中的select返回我们要删除的正确数量的记录,但对它们进行分组,使其实际数量增加一倍

加入后,它会显示所有记录,但我只想删除最旧的记录

如何做到这一点?

在SQL Server 2005及更高版本中:

WITH    q AS
        (
        SELECT  *,
                ROW_NUMBER() OVER (PARTITION BY itemid, fieldid, version ORDER BY updated DESC) AS rn
        FROM    versionedFields
        )
DELETE
FROM    q
WHERE   rn > 1
尝试以下方法:

DELETE FROM dbo.VersionedFields w WHERE w.version < (SELECT MAX(version) FROM dbo.VersionedFields)
当然,您希望将MAXversion限制为您要删除的字段的版本。

如果您说的是SQL结构化查询语言,但实际上指的是SQL Server,即Microsoft Relational数据库系统,并且如果您使用的是SQL Server 2005或更新版本,则可以为此使用CTE公共表表达式

使用此CTE,您可以按照某些标准(即ItemId或列的组合)对数据进行分区,并让SQL Server为每个分区的所有行编号,从1开始,按照其他标准(即可能的版本或其他列)排序

因此,请尝试以下方法:

;WITH PartitionedData AS
(
    SELECT 
       itemid, fieldid, version, 
       ROW_NUMBER() OVER(PARTITION BY ItemId ORDER BY version DESC) AS 'RowNum'
    FROM dbo.VersionedFields
)
DELETE FROM PartitionedData
WHERE RowNum > 1
基本上,您是按照一些标准对数据进行分区,并对每个分区编号,每个新分区从1开始,按照其他一些标准(例如日期或版本)排序

因此,对于每个数据分区,最新条目的RowNum=1,通过具有相同partitionno值而属于同一分区的任何其他条目的值都将按顺序编号,从2到该分区中有多少行


如果您只想保留最新的条目-删除RowNum大于1的任何内容,您就完成了

您可能需要查看删除重复行中较早的一行

本质上,该技术使用分组或可选的窗口来查找组的最小id值,以便将其删除。删除值为maxrow标识符的行可能更准确

因此:

删除唯一索引 加载数据 最好在事务中使用分组机制删除数据,以便在出现错误时回滚,然后提交 重新创建索引。
请注意,在大表上重新创建索引可能需要很长时间。

marc_的解决方案是一种优雅的方法。