重命名 MySQL 中的重复行,WHERE IT () - 无法正常工作

Rename duplicate rows in MySQL, WHERE IN () - dosen't works fine

我从这里开始: Rename duplicate rows in MySQL

SELECT  mid(s,instr(s,',')+1) as dubid
FROM (
      SELECT group_concat(id ORDER BY id ASC) s, count(*) c
      FROM   `...`
      GROUP BY field
      HAVING c > 1) as z

似乎工作正常并且 returns 像

这样的可疑行
1
3,5,6
8
10,15

所以我做了这个:

set @suf:=0;
UPDATE `table_cf_vendlist` 
SET    `cf_vendlist` = concat(`cf_vendlist`, ' \(', @suf:=@suf+1,'\)')
WHERE  `cf_vendlistid` IN ({SELECT  mid...})

但它只重命名每行的第一个 ID。那么我怎样才能让它发挥作用呢?另外如何为每一行取消@suf 计数器? 没有 PHP。仅MySQL!

set @suf:=0;
set @last := 0;
UPDATE `vtiger_cf_vendlist` t1
INNER JOIN (
   SELECT MIN(cf_vendlistid) as id, cf_vendlist
   FROM   vtiger_cf_vendlist 
   GROUP BY cf_vendlist) AS unique1 
ON (t1.cf_vendlist = unique1.cf_vendlist)
SET    t1.`cf_vendlist` = concat(t1.`cf_vendlist`, ' \(', 
         @suf := if (@last = t1.cf_vendlistid, @suf+1, 1 and @last := t1.cf_vendlist), '\)')
WHERE t1.cf_vendlistid <> unique1.id

但我不确定 t1.cf_vendlist 在哪里,unique1.cf_vendlist 在哪里。名称中的结果也是 0 和 1,每个 id 集没有递增和归零。但是,仍然需要重命名。

这是 运行 的一些数据 sqlfiddle.com:

CREATE TABLE IF NOT EXISTS `table_cf_vendlist` (
  `cf_vendlistid` int(11) NOT NULL AUTO_INCREMENT,
  `cf_vendlist` varchar(200) NOT NULL,
  PRIMARY KEY (`cf_vendlistid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=78 ;


INSERT INTO `table_cf_vendlist` (`cf_vendlistid`, `cf_vendlist`) VALUES
(2, 'Поставщик 2'),
(3, 'Поставщик 3'),
(4, 'Поставщик 4'),
(5, 'del 1'),
(6, 'Поставщик 1 (1)'),
(7, 'Поставщик 1 (2)'),
(8, 'пост 66'),
(9, 'пост 77'),
(10, 'пост 67'),
(11, 'пост 5'),
(12, '123'),
(13, '102'),
(14, 'пост 5 (1)'),
(15, 'пост 70'),
(47, 'Поставщик 1'),
(48, 'Поставщик 2'),
(49, 'Поставщик 3'),
(50, 'Поставщик 4'),
(51, 'del 1'),
(52, 'Поставщик 1'),
(53, 'Поставщик 1'),
(54, 'пост 5'),
(55, '124523452346256456'),
(56, 'пост 66'),
(57, 'пост 77'),
(58, 'пост 5'),
(59, 'пост 5'),
(60, 'пост 5'),
(61, 'пост 67'),
(62, '123'),
(63, '123'),
(64, '123'),
(65, 'пост 5'),
(66, 'пост 68'),
(67, '123'),
(68, '123'),
(69, '123'),
(70, '123'),
(71, '102'),
(72, 'пост 5'),
(73, 'пост 70');

UPD

我们得到了

52  Поставщик 1 (11)
53  Поставщик 1 (12)

而不是

52  Поставщик 1 (3)
53  Поставщик 1 (4)

48  Поставщик 2 (13)
49  Поставщик 3 (14)
50  Поставщик 4 (15)

而不是

48  Поставщик 2 (2)
49  Поставщик 3 (2)
50  Поставщик 4 (2)

更新 2:

set @suf:=0;
set @last := 0;
UPDATE     table_cf_vendlist t
INNER JOIN (SELECT cf_vendlistid, concat(cf_vendlist, ' (', 
                   @suf := if (STRCMP(@last1, cf_vendlist) = 0,
                               @suf+1,
                               1 or @last := cf_vendlist), ')') as new_label
           FROM (
                 SELECT     t1.cf_vendlistid, t1.cf_vendlist, unique1.id as reference_id
                 FROM       table_cf_vendlist t1
                 INNER JOIN (SELECT  MIN(cf_vendlistid) as id, cf_vendlist
                             FROM     table_cf_vendlist
                             GROUP BY cf_vendlist) AS unique1
                             ON       t1.cf_vendlist = unique1.cf_vendlist
                 ORDER BY   cf_vendlist, cf_vendlistid
                ) AS t1_sorted

           WHERE   t1_sorted.cf_vendlistid <> t1_sorted.reference_id)

           AS t1_sorted_labeled

ON         t.cf_vendlistid = t1_sorted_labeled.cf_vendlistid

SET        t.cf_vendlist = t1_sorted_labeled.new_label;

有效。但是 1 or @last := cf_vendlist 是一个允许 return 1 or 0(and) 而不是 cf_vendlist 字符串的 hack(见下面我的评论)

我在 sqlfiddle 中有一个解决方案。要了解它的工作原理,

1)看子查询t1_sorted

SELECT     t1.cf_vendlistid, t1.cf_vendlist, unique1.id as reference_id
FROM       table_cf_vendlist t1
INNER JOIN (SELECT MIN(cf_vendlistid) as id, cf_vendlist
            FROM   table_cf_vendlist
            GROUP BY cf_vendlist) AS unique1
ON          t1.cf_vendlist = unique1.cf_vendlist
WHERE       t1.cf_vendlistid <> unique1.id
ORDER BY    cf_vendlist, cf_vendlistid

其中 returns 结果如图所示。 1.

2a) 在子查询 t1_sorted_labeled 中,结果预计会删除每个组中第一次出现的 cf_vendlist 和

2b) 使用 cf_vendlist 和(拷贝数)

创建了一个额外字段 new_label

3) 最后,原始查询在 UPDATE 语句中与此子查询连接,它只是将 new_label 复制到 cf_vendlist

因此,完整答案:

set @suf:=0;
set @last := 0;

UPDATE     table_cf_vendlist t
INNER JOIN (SELECT cf_vendlistid, concat(cf_vendlist, ' (', 
               @suf := if (STRCMP(@last, cf_vendlist) = 0,
                           @suf+1,
                           1 and length(@last := cf_vendlist)), ')') as new_label
           FROM (
                 SELECT     t1.cf_vendlistid, t1.cf_vendlist, unique1.id as reference_id
                 FROM       table_cf_vendlist t1
                 INNER JOIN (SELECT  MIN(cf_vendlistid) as id, cf_vendlist
                             FROM     table_cf_vendlist
                             GROUP BY cf_vendlist) AS unique1
                             ON       t1.cf_vendlist = unique1.cf_vendlist
                 ORDER BY   cf_vendlist, cf_vendlistid
                ) AS t1_sorted

           WHERE   t1_sorted.cf_vendlistid <> t1_sorted.reference_id)

           AS t1_sorted_labeled

ON         t.cf_vendlistid = t1_sorted_labeled.cf_vendlistid

SET        t.cf_vendlist = t1_sorted_labeled.new_label;

顺便说一句,你真的应该在 cf_vendlist 上有一个索引。