繁体   English   中英

更新一列,使重复的​​值变得唯一

[英]update a column so duplicated values becomes unique

title有很多重复值,不止一次。

我需要更新该列,例如,如果'gold'重复 - 它变为'gold 1''gold 2'等。

像这样的东西:

$st = $db->query("select id, title from arts order by title asc");
$st->execute();
$x = 0;
while($row = $st->fetch()){
    $title = $row['title'];
    //if($title.is duplicated){
        $x++;
        $title .= ' ' . $x;
        $stb = $db->query("update arts set title = '" . $title . "' where id = " . $row['id']);
        $stb->execute();
    }
}

有什么帮助吗?

在纯 SQL 中执行此操作会比使用 PHP 更有效。 这是一种使用窗口函数的方法,可在 MySQL 8.0 中使用。

您可以使用子查询来计算每条记录存在多少title重复,并为具有相同title的记录组中的每条记录分配一个等级。 然后,您可以将子查询与要更新的表进行JOIN 如果存在多个记录,您可以将行号附加到组中的每条记录。

询问:

UPDATE arts a
INNER JOIN (
    SELECT 
        id, 
        title, 
        COUNT(*) OVER(PARTITION BY title) cnt,
        ROW_NUMBER() OVER(PARTITION BY title ORDER BY id) rn
    FROM arts
) b ON a.id = b.id
SET a.title = CONCAT(a.title, b.rn)
WHERE cnt > 1;

DB Fiddle 上的演示

样本数据:

| id  | title  |
| --- | ------ |
| 10  | silver |
| 20  | gold   |
| 30  | gold   |
| 40  | bronze |
| 50  | gold   |
| 60  | bronze |

运行更新查询后的结果:

| id  | title   |
| --- | ------- |
| 10  | silver  |
| 20  | gold1   |
| 30  | gold2   |
| 40  | bronze1 |
| 50  | gold3   |
| 60  | bronze2 |

请参阅下面对我有用的代码

// Create connection
$conn = new mysqli($servername, $username, $password,$dbname);
// get all row  
$sql = "select id, title from arts order by title asc";
$result = $conn->query($sql);

while ($row=$result->fetch_assoc()) {   
    $title=$row['title'];
    // select where title is same
    $sql = "select * from arts where title='".$title."'";
    $result2 = $conn->query($sql);
    // if number of row is greater then one 
    if ($result2->num_rows > 1){
        $x=0;
        while ($row2=$result2->fetch_assoc()) {
            $id=$row2['id'];
            // skip first row 
            if($x>0){
                $newTitle=$title.' '.$x;
                $uquery = "update arts set title='".$newTitle."' where title='".$title."' and id=$id";                  
                $update = $conn->query($uquery);
            }
            $x++;
        }
    }   
}

查询前

并在查询运行后

下图

这适用于 MySql 5.7:

update arts a inner join (
  select * from (
    select t.id,
      (
        select count(*) + 1 from arts 
        where id < t.id and title = t.title 
      ) counter
    from arts t
  ) t 
) t on t.id = a.id
set a.title = concat(a.title, ' ', t.counter)
where a.title in (
  select h.title from (
    select title from arts
    group by title
    having count(*) > 1    
  ) h 
);

请参阅演示
对于数据:

| id  | title    |
| --- | -------- |
| 1   | silver   |
| 2   | gold     |
| 3   | diamond  |
| 4   | bronze   |
| 5   | gold     |
| 6   | bronze   |
| 7   | gold     |

结果是

| id  | title    |
| --- | -------- |
| 1   | silver   |
| 2   | gold 1   |
| 3   | diamond  |
| 4   | bronze 1 |
| 5   | gold 2   |
| 6   | bronze 2 |
| 7   | gold 3   |

我认为在 SQL 中执行此操作会更有效,但是您可以执行一个函数来验证重复项,如下所示:

function isDuplicated( $title, $db ){   
    $dp = $db->query("SELECT * FROM arts WHERE title = $title");        
    if ( $dp->num_rows > 1)
        return true;

    return false;            
}


$st = $db->query("select id, title from arts order by title asc");
$st->execute();
$x = 0;
while($row = $st->fetch()){
    $title = $row['title'];
    if( isDuplicated( $title, $db ) ){
        $x++;
        $title .= ' ' . $x;
        $stb = $db->query("update arts set title = '" . $title . "' where id = " . $row['id']);
        $stb->execute();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM