如何使用找到的组的新值更新行并使其尽可能快?

Posted

技术标签:

【中文标题】如何使用找到的组的新值更新行并使其尽可能快?【英文标题】:How to update rows with new values for groups found and make this as fast as posible? 【发布时间】:2021-02-15 13:18:21 【问题描述】:

我有一张表,其中包含以下字段:id、client_id、visit_id、number_of_visit。

此表可以有 30k 到 100+k 行数据。主键是client_id 和visit_id。 (我不能有这两个值相同的行,但同时 client_id 可以出现超过 1 次具有不同的 visit_id 等等)。

我要做的就是给字段number_of_visit写值,这个值应该是本次访问的序号(第一次、第二次、第三次等)。我有 visit_id 字段,它实际上是一个很大的数字,我需要将其排序为“ASC”并相应地将值写入number_of_visit。我有这个:

id   client_id   visit_id   number_of_visit
1    103         10         0
2    103         11         0
3    104         12         0
4    105         13         0
5    105         15         0
6    105         16         0

我想这样做:

id   client_id   visit_id   number_of_visit
1    103         10         1
2    103         11         2
3    104         12         1
4    105         13         1
5    105         15         2
6    105         16         3

我以与visit_id 值在ASC 的顺序相同的顺序从1 到n 将值写入number_of_visit

此表可以有超过 1 行具有相同的 client_id,但不能有具有相同的 visit_id 的行,因为一个 visit_id 总是相对于特定的 client_id。我需要获取此表中所有client_id 中的所有visit_id,并使用代表序列号的数字1、2、3 更新这些行的number_of_visit 字段。 (如果这是第一次访问,或者是第二次、第三次等等......)。

我有这个 php 代码:

$visit_ids = [];

$sql = "SELECT clientID, GROUP_CONCAT(id) as 'visit_ids' FROM table_report GROUP BY clientID";
$stmt = $pdo->prepare($sql);
$stmt->execute();

while ($row = $stmt->fetch()) 

    $visit_ids = explode(',', $row['visit_ids']);

    $counter = 1;
    foreach ($visit_ids as $id) 
    
        $query = "UPDATE table_report SET number_of_visit = :value WHERE id = :id";
        $statement = $pdo->prepare($query);
        $statement->execute([':value' => $counter, ":id" => $id]);
        $counter++;
    

但主要问题是它太慢了。该表现在包含大约 40k 行,但可能超过 100k+。当它是 40k 时,大约需要一两个小时才能完成。

我能做些什么来加快速度?我在这些字段上有索引。

这里还有 EXPLAIN 输出:

【问题讨论】:

【参考方案1】:

使用row_number():

select t.*, row_number() over(partition by client_id order by visit_id) number_of_visit
from table_report t

如果您想要update 声明:

update table_report t
inner join (
    select id, row_number() over(partition by client_id order by visit_id) number_of_visit
    from table_report t1
) t1 on t1.id = t.id
set t.number_of_visit = t1.number_of_visit

【讨论】:

谢谢,这正是我需要的。我实际上很接近,但由于某种原因开始做错事。

以上是关于如何使用找到的组的新值更新行并使其尽可能快?的主要内容,如果未能解决你的问题,请参考以下文章

如何使 UIImageView 可点击并使其执行某些操作? (迅速)

如何使用 C# 程序中的新值快速更新表中的所有行

如何在sql中找到具有多个最大值的组的最大值?

如何拥有多个带有标题的 UICollectionView 并使其水平滑动

如何在 Mountain Lion 中启用 php.ini 并使其工作?

如何重置为提交并使其成为大师?