无法从 MariaDB 10 中删除重复项
Can't remove duplicates from MariaDB 10
我很难从数据库中删除重复项。它是 MariaDB(协议版本:10、10.3.34-MariaDB Server)。我需要删除三列相等的行。我试图使用 WITH 子句,但数据库抛出无法识别的错误 'WITH',所以我专注于传统方式。
我需要删除 foreignId
、column1
和 column2
相等的行。
我正在检查是否有像
这样的重复项
SELECT foreignId, column1, column2, COUNT(*)
FROM table1
GROUP BY foreignId, column1, column2
HAVING COUNT(*) > 1
正在尝试删除重复项...
DELETE table1
FROM table1
INNER JOIN (
SELECT
p.id,
p.foreignId,
p.column1,
p.column2,
ROW_NUMBER() OVER (
PARTITION BY
p.column1,
p.column2,
p.foreignId
ORDER BY
p.foreignId,
p.column2,
p.column1
) AS row_number
FROM table1 p
GROUP BY p.foreignId, p.column1, p.column2
) dup
ON table1.column1 = dup.column1
WHERE dup.row_number > 1;
我对这段代码进行了大量修改,但仍然无法使其按预期工作...我做错了什么?
您的查询有一些问题:
- 您需要删除子查询中的
GROUP BY
- 您应该将
OVER
子句中的 ORDER BY
更改为 ORDER BY p.ts DESC
(其中 ts
是时间戳列的名称)
- 您需要在唯一的
id
列上 JOIN
;否则,您将删除任何具有重复值的行,即 ON table.id = dup.id
那会给你:
DELETE table1
FROM table1
INNER JOIN (
SELECT
p.id,
ROW_NUMBER() OVER (
PARTITION BY
p.column1,
p.column2,
p.foreignId
ORDER BY
p.ttimestamp DESC
) AS rn
FROM table1 p
) dup
ON table1.id = dup.id
WHERE dup.rn > 1
请注意,我不会使用 row_number
作为列别名,因为它是一个保留字,所以我在上面将其更改为 rn
。
上的演示(感谢@JonasMetzler)
请注意,如果重复行也可能具有相同的时间戳值,则此查询将删除这些行的随机选择。如果您想要确定性结果,请将 ORDER BY
子句更改为
ORDER BY
p.ttimestamp DESC,
p.id DESC
这将保留最高的行(如果您在 p.id
之后删除 DESC
,则保留最低的行)id
值。
假设您有一个像 id 这样的唯一列,您可以执行以下操作:
DELETE FROM table1 WHERE ID NOT IN
(SELECT x.id FROM
(SELECT MAX(id) id, MAX(foreignId) foreignId,
MAX(column1) column1, MAX(column2) column2
FROM table1
WHERE ttimestamp IN (SELECT MAX(ttimestamp) FROM table1
GROUP BY foreignID, column1, column2)
GROUP BY foreignId, column1, column2)x);
请在此处查看工作示例:db<>fiddle
我很难从数据库中删除重复项。它是 MariaDB(协议版本:10、10.3.34-MariaDB Server)。我需要删除三列相等的行。我试图使用 WITH 子句,但数据库抛出无法识别的错误 'WITH',所以我专注于传统方式。
我需要删除 foreignId
、column1
和 column2
相等的行。
我正在检查是否有像
这样的重复项SELECT foreignId, column1, column2, COUNT(*)
FROM table1
GROUP BY foreignId, column1, column2
HAVING COUNT(*) > 1
正在尝试删除重复项...
DELETE table1
FROM table1
INNER JOIN (
SELECT
p.id,
p.foreignId,
p.column1,
p.column2,
ROW_NUMBER() OVER (
PARTITION BY
p.column1,
p.column2,
p.foreignId
ORDER BY
p.foreignId,
p.column2,
p.column1
) AS row_number
FROM table1 p
GROUP BY p.foreignId, p.column1, p.column2
) dup
ON table1.column1 = dup.column1
WHERE dup.row_number > 1;
我对这段代码进行了大量修改,但仍然无法使其按预期工作...我做错了什么?
您的查询有一些问题:
- 您需要删除子查询中的
GROUP BY
- 您应该将
OVER
子句中的ORDER BY
更改为ORDER BY p.ts DESC
(其中ts
是时间戳列的名称) - 您需要在唯一的
id
列上JOIN
;否则,您将删除任何具有重复值的行,即ON table.id = dup.id
那会给你:
DELETE table1
FROM table1
INNER JOIN (
SELECT
p.id,
ROW_NUMBER() OVER (
PARTITION BY
p.column1,
p.column2,
p.foreignId
ORDER BY
p.ttimestamp DESC
) AS rn
FROM table1 p
) dup
ON table1.id = dup.id
WHERE dup.rn > 1
请注意,我不会使用 row_number
作为列别名,因为它是一个保留字,所以我在上面将其更改为 rn
。
请注意,如果重复行也可能具有相同的时间戳值,则此查询将删除这些行的随机选择。如果您想要确定性结果,请将 ORDER BY
子句更改为
ORDER BY
p.ttimestamp DESC,
p.id DESC
这将保留最高的行(如果您在 p.id
之后删除 DESC
,则保留最低的行)id
值。
假设您有一个像 id 这样的唯一列,您可以执行以下操作:
DELETE FROM table1 WHERE ID NOT IN
(SELECT x.id FROM
(SELECT MAX(id) id, MAX(foreignId) foreignId,
MAX(column1) column1, MAX(column2) column2
FROM table1
WHERE ttimestamp IN (SELECT MAX(ttimestamp) FROM table1
GROUP BY foreignID, column1, column2)
GROUP BY foreignId, column1, column2)x);
请在此处查看工作示例:db<>fiddle