表格有一些重复的记录。这是一个示例:
create table TestStage
(
primKey int,
name varchar(50),
Flag varchar(10)
)
INSERT INTO TestStage VALUES(12,'DDD','I')
INSERT INTO TestStage VALUES(15,'EEE','N')
INSERT INTO TestStage VALUES(12,'AAA','I')
INSERT INTO TestStage VALUES(16,'MMM','N')
primKey
是基于此列的记录被定义为重复或不重复的列。因此在上面的例子中,第1行和第3行是重复的。我需要删除第1行并保留第3行。
我在其他一些帖子中使用的CTE如下:
WITH cte AS
(
SELECT
ROW_NUMBER() OVER(PARTITION BY primKey ORDER BY primKey) AS [rn]
FROM
TestStage
)
DELETE cte
WHERE [rn] > 1
但这显然会删除第3行而不是第1行。
我该如何处理?有几点需要注意......
这是一个示例表。实际表中的重复记录,由不一定是数字的键组合确定。
我现在无法为表创建标识列。
该表在键上有一个索引,用于确定它是否重复(在此示例中为primKey)是否可以使用。
感谢。
答案 0 :(得分:2)
可能你的误解是你认为表有一些内在的顺序。没有桌子有订单。查询必须建立订单。您需要定义一些有意义的ORDER BY
子句来确定要删除的行。
如果您依赖“桌面订单”并且没有其他方法可以选择行,那么您无能为力。
现在你的ORDER BY primKey
事物完全没有效果,因为在每个分区中,所有primKey
值都是相同的。这与ORDER BY (SELECT NULL)
相同。
要保留的分区的行号的最高值
没有内在的行号。你需要接受这个事实。
答案 1 :(得分:0)
以下是70-461培训套件的文字:
似乎输出按empid排序,但事实并非如此 保证。更令人困惑的是,如果你运行查询 反复地,似乎结果一直在返回 订购;但同样,这不能保证。当数据库引擎时(SQL 在这种情况下服务器)处理此查询,它知道它可以返回 任何顺序的数据都是因为没有明确的指令 以特定顺序返回数据。可能是因为 优化和其他原因,SQL Server数据库引擎选择 这次以特定方式处理数据。甚至还有一些 如果是物理的话,这种选择会重复的可能性 情况保持不变。但是两者之间存在很大差异 由于优化和其他原因而可能发生的事情 什么是实际保证。
数据库引擎可能 - 有时也可能 确实可以影响行所在的选择 知道可以自由地回来了。这种变化的例子 在选择中包括数据分布的变化,可用性 物理结构,如索引和资源的可用性 像CPU和内存。此外,随着发动机的变化 升级到更新版本的产品,甚至是申请后 一个服务包,优化方面可能会改变。反过来,这样 除其他外,更改可能会影响行的顺序 结果。
简而言之,这不足以强调:一个查询 没有明确的指示来返回a中的行 特定顺序不保证结果中的行顺序。 查询的子句,这是下一节的重点。
答案 2 :(得分:-1)
你可以试试这个......它"可能"保留表中当前订单的任何内容。
;
WITH cte
AS (SELECT
primKey,
name,
ROW_NUMBER() OVER (PARTITION BY primKey ORDER BY primKey) AS [rn]
FROM
TestStage
)
DELETE
t
FROM
TestStage t
JOIN cte ON t.primKey = cte.primKey
AND t.name = cte.NAME
WHERE
cte.rn < (SELECT MAX (rn) FROM cte WHERE primKey = t.primKey)
此处有一项测试,您可以查看是否可以更改订单。计算出订单中断所需的次数。然后弄清楚它是否值得冒险。
DECLARE @TestStage TABLE(
primKey int,
name varchar(50),
Flag varchar(10)
)
INSERT INTO @TestStage VALUES
(12,'DDD','I'),(15,'EEE','N'),(12,'AAA','I'),(16,'MMM','N')
DECLARE @TestStageOrder TABLE(
primKey int,
name varchar(50),
Flag varchar(10),
[order] int
)
DECLARE @TestCount INT = 0
WHILE @TestCount < 100000
BEGIN
INSERT INTO @TestStageOrder
SELECT *, ROW_NUMBER() OVER (PARTITION BY primKey ORDER BY primKey)
FROM @TestStage
SET @TestCount = @TestCount + 1
END
SELECT primKey, name, Flag, [order], COUNT(*)
FROM @TestStageOrder
GROUP BY primKey, name, Flag, [order]