【问题标题】:Store procedures for delete a repeat records删除重复记录的存储程序
【发布时间】:2020-02-05 17:21:12
【问题描述】:

您好,我在 MySQL 中有一个表:

“合同”,其中我为每个 client_id 创建了 3 条记录,但是后端的一个错误在某些 client_id 上创建了更多记录,我尝试创建一个存储过程来删除重复记录,例如 3 条记录:

ID cliente_id amount_preapprove
1     1        10000
2     1        12000
3     1        14000
4     1        10000 // <- record repeat 
5     1        10000 // <- record repeat 
6     1        14000 // <- record repeat 
7     2        7000 
8     2        8000 
9     2        9000 
10    2        7000 // <- record repeat for client_id 2
11    2        8000 // <- record repeat 
12    2        9000 // <- record repeat 
... N Clients repeat

我需要为每个用户获取不同的 amount_preapprove,截断表并将结果插入存储过程?

每个客户我只需要 3 条记录

【问题讨论】:

  • 你的服务器版本是多少?我认为您不需要为此使用存储过程。
  • helo @PaulSpiegel 谢谢,我在问题中添加了一张图片

标签: mysql sql stored-procedures


【解决方案1】:

我不确定您是否真的想为每个客户保留 3 条记录。在您的示例数据中,您看起来更像是在尝试删除 (cliente_id, amount_preapprove) 上的重复项。

如果是这样,您可以使用以下查询:

delete t
from mytable t
inner join mytable t1 
    on  t1.cliente_id = t.client_id
    and t1.amount_preapprove = t.amount_preapprove
    and t1.id < t.id

此查询将删除所有存在另一个记录的记录,该记录具有相同的cliente_idamount_preapprove,但较小的id。换句话说,这会删除重复项,同时保留 id 最小的记录。

【讨论】:

    【解决方案2】:

    你可以使用row_number():

    select t.*
    from (select t.*,
                 row_number() over (partition by client_id order by id) as seqnum
          from t
        ) t
    where seqnum <= 3;
    

    您也可以使用标量比较:

    select t.*
    from t
    where t.seqnum <= any (select t2.seqnum
                           from t t2
                           where t2.client_id = t.client_id
                           order by t2.seqnum
                           limit 1 offset 2
                          );
    

    any 是这样,当每个客户端少于三个时,查询会返回所有行。

    【讨论】:

    • 您好,谢谢,我需要从表“contracts”中获取超过 3 条的所有记录来传递删除重复记录,并且在截断后只在表上重新插入 3 条
    【解决方案3】:

    以下查询将保留client_id 的前三行(按 ID 排序)并删除其他任何内容:

    delete t
    from my_table t
    join (
      select t1.ID
      from my_table t1
      where t1.ID > (
        select t2.ID
        from my_table t2
        where t2.cliente_id = t1.cliente_id
        limit 1
        offset 2
      )
    ) x using(ID);
    

    在该操作之后,数据将是:

    | ID  | cliente_id | amount_preapprove |
    | --- | ---------- | ----------------- |
    | 1   | 1          | 10000             |
    | 2   | 1          | 12000             |
    | 3   | 1          | 14000             |
    | 7   | 2          | 7000              |
    | 8   | 2          | 8000              |
    | 9   | 2          | 9000              |
    

    View on DB Fiddle

    在 MySQL 8 中,使用 CTE 和 ROW_NUMBER() 窗口函数会更简单一些:

    with cte as (
      select ID, row_number() over (partition by cliente_id order by ID) as rn
      from my_table
    )
    delete t
    from my_table t
    join cte using(ID)
    where rn > 3;
    

    View on DB Fiddle

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-16
      • 1970-01-01
      • 2021-03-17
      • 2012-12-14
      • 1970-01-01
      • 1970-01-01
      • 2016-01-07
      相关资源
      最近更新 更多