在sql中重命名每个组的重复项

时间:2018-04-04 15:47:04

标签: mysql sql

我想写一个会更新每组重复项的查询:

  INPUT
+-------+-------+
| group | name  |
+-------+-------+
|     1 | name1 |
|     1 | name1 |
|     1 | name1 |
|     1 | name2 |
|     2 | name1 |
|     2 | name1 |
|     3 | name1 |
|     3 | name2 |
+-------+-------+

 OUTPUT  
+-------+----------------+
| group | name           |
+-------+----------------+
|     1 | name1          |
|     1 | name1 - Copy 1 |
|     1 | name1 - Copy 2 |
|     1 | name2          |
|     2 | name1          |
|     2 | name1 - Copy 1 |
|     3 | name1          |
|     3 | name2          |
+-------+----------------+

这里有类似的东西Renaming the duplicate data in sql,但我的问题是如何处理群组。 如何命名这个重复项并不是那么重要,但如果我可以按照我的例子中的说明进行操作,那将会很酷。

4 个答案:

答案 0 :(得分:2)

如果您有主键id列,请尝试以下操作:

update (
    select `group`, name, min(id) as min_id
    from test
    group by `group`, name
) x
join test t using (`group`, name)
set t.name =
    case when t.id <> x.min_id
    then concat(t.name, ' - Copy ', t.id - x.min_id)
    else t.name
    end
;

演示:http://rextester.com/AWEX77086

这是另一种方式,可能更慢,但会保证连续的拷贝数。

update (
    select l.id, count(*) as copy_nr
    from test l
    join test r
      on  r.group = l.group
      and r.name  = l.name
      and r.id < l.id
    group by l.id
) x
join test t using (id)
set t.name = concat(t.name, ' - Copy ', x.copy_nr);

演示:http://rextester.com/NWSF57017

答案 1 :(得分:1)

请尝试以下操作,将“组”替换为“组”。

好的,我被指出这是一个MySQL问题,因此以下不适用于MySQL,但只适用于t-sql。

SELECT Groups,
    CASE WHEN Duplicate > 1
            THEN Name + ' - Copy ' + CONVERT(VARCHAR(10), Duplicate)
         ELSE Name
    END AS Name
FROM
(
    SELECT Groups,
        Name,
        ROW_NUMBER() OVER(PARTITION BY Name, Groups ORDER BY Name ) As Duplicate
    FROM TableName
) AS Data
ORDER BY Groups

enter image description here

答案 2 :(得分:1)

这是未经测试的,但您可以使用变量来模拟许多其他RDBMS中的LAG函数(更多信息here)。

我们的想法是存储组和名称字段,并在更新之前与它们进行比较。

SET @RowNumber = 0;
SET @PreviousGroup = NULL;
SET @PreviousName = NULL;

SELECT
  @PreviousGroup AS PreviousGroup,
  @PreviousName AS PreviousName,
  CASE 
    WHEN @PreviousGroup = `group` AND @PreviousName = `name` THEN (@RowNumber := @RowNumber + 1)
    ELSE @RowNumber := 0
  END AS `Counter`,
  CASE 
    WHEN @PreviousGroup = `group` AND @PreviousName = `name` THEN CONCAT(`name`,'- Copy ',@RowNumber)
    ELSE `name`
  END AS `Name`,
  @PreviousGroup := `group` AS RawGroup,
  @PreviousName := `name` AS RawName
FROM
  tbl1
ORDER BY
  `group` ASC,
  `name` ASC;

答案 3 :(得分:1)

您可以使用变量执行此操作。我建议:

set @i = 0;
set @gn := '';

update t
    set name = concat_ws(' - Copy ', name,
                         nullif(if(@gn = concat_ws(':', group, name), @i := @i + 1,
                                   if(@gn := concat_ws(':', group, name), @i := 1, @i := 1)
                                  ), 0)
    order by t.group, name;
相关问题