【问题标题】:Find and remove MySQL row duplicates that are right after each other查找并删除紧随其后的 MySQL 行重复
【发布时间】:2018-07-09 13:10:47
【问题描述】:

我正在尝试查找并删除紧随其后的 MySQL 行重复,而不是查找所有行,即使它们不是紧随其后。

SELECT DISTINCT(content) AS contentMsg, COUNT(*) AS cnt, `ticketId`,`date` 
FROM ticketsReplies 
WHERE username = 'X' 
GROUP BY contentMsg, ticketId 
HAVING cnt > 1 
ORDER BY cnt DESC

这是我当前的代码。但是,如果一张票中只有两个相同的答案,而不是它们必须是一个接一个的 ID(如果您发送 POST 请求并且它失败并且您刷新等,则可能会发生这种情况),这会发现重复项。

我将如何找到彼此之间只有 1 个 ID 的那些。

所以找到例如1,2,3,4,5,6,7 而不是 1,3,9,11

例如如果你有

ID                     EMAIL                
---------------------- -------------------- 
1                      aaa                  
2                      bbb                  
3                      bbb                  
4                      bbb                  
5                      ddd                  
6                      eee                  
7                      aaa                  
8                      aaa                  
9                      bbb

如果你有这个,它应该找到以下 ID: 2,3,4 但不是 9,因为它不是直接在 4 之后,即使它是重复的。

它也应该找到 7,8 但不是 1,因为它们不是紧挨着的。

【问题讨论】:

  • 请注意,DISTINCT 不是函数,而且它不太可能出现在聚合查询中(聚合函数内除外)。
  • 除此之外,您的 GROUP BY 不是 ANSI 有效的,这意味着它将在 MySQL 服务器上失败,在 sql_mode 中启用了``ONLY_FULL_GROUP_BY`。它将在没有该 sql_mode 但将为 SELECT 中未在 GROUP BY 中命名的每个列名生成不可信数据,在这种情况下,这是列日期..
  • @Strawberry 我已经更新了我的 OP 以便更好地理解。

标签: php mysql


【解决方案1】:

例如:

SELECT id 
  FROM 
     ( SELECT x.id  FROM my_table x JOIN my_table y ON y.email = x.email AND y.id = x.id + 1 ) a 
 UNION 
     ( SELECT y.id FROM my_table x JOIN my_table y ON y.email = x.email AND y.id = x.id + 1 );

【讨论】:

  • 我知道 OP 没有提及,但是如果他在 ID 列中有空白会发生什么?假设id=5 email=bbb,下一个是id=7 email=bbb,因为他删除了id=6
  • @Michel OP 必须说明他们想如何处理这个问题,但无论哪种方式,修复都相当简单。
【解决方案2】:

如果您的id 列表中存在空白(例如5, 6, 9, 11),那么简单地比较id = id+1 是行不通的。我想出的解决方案是创建两个具有连续行号的相同临时表。在这种情况下,您可以根据行数安全地比较行,即使 id 有间隙。

DELETE FROM tab WHERE id IN (

SELECT A.id
FROM 
    (
    SELECT row_nr, id, email FROM (
        SELECT
            (@cnt1 := @cnt1 + 1) AS row_nr,
            t.id,t.email
        FROM tab AS t
          CROSS JOIN (SELECT @cnt1 := 0) AS d
        ORDER BY t.id
        ) x
    ) A
INNER JOIN 
    (
    SELECT row_nr, id, email FROM (
        SELECT
            (@cnt2 := @cnt2 + 1) AS row_nr,
            t.id,t.email
        FROM tab AS t
          CROSS JOIN (SELECT @cnt2 := 0) AS d
        ORDER BY t.id
        ) x
    ) B
ON A.row_nr-1 = B.row_nr AND A.email=B.email

)

(SELECT row_nr, id, email FROM ... ) x 的两个部分创建了两个相同的表 A 和 B,就像

row_nr   id  email
 1       1   aaa
 2       4   aaa
 3       5   bbb
 4       9   aaa
 5       11  aaa

然后你可以比较顺序的row-nr和email:

ON A.row_nr-1 = B.row_nr AND A.email=B.email

选择结果 ID 会为您提供 ID 的 4, 11,它们是重复的。然后你可以删除那些id:

DELETE FROM tab WHERE id IN ( ... )

这是一个 Fiddle 来测试 SELECT 部分。

注意:在您在家尝试之前,请备份您的表!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-27
    • 2012-06-20
    • 1970-01-01
    • 2012-12-29
    • 2021-02-21
    • 2011-10-26
    • 2020-08-24
    • 2021-04-12
    相关资源
    最近更新 更多