2

为了修复错误,我必须遍历表中的所有行,将缓存的子项数更新为其实际值。表中事物的结构形成一棵树。

在rails中,以下是我想要的:

Thing.all.each do |th|
  Thing.connection.update(
    "
      UPDATE #{Thing.quoted_table_name} 
        SET children_count = #{th.children.count}
        WHERE id = #{th.id}
    "
  )
end

有没有办法在单个 MySQL 查询中做到这一点?或者,有没有办法在多个查询中执行此操作,但在纯 MySQL 中?

我想要类似的东西

UPDATE table_name
  SET children_count = (
    SELECT COUNT(*) 
      FROM table_name AS tbl 
      WHERE tbl.parent_id = table_name.id
  )

除了以上不起作用(我明白为什么不起作用)。

4

2 回答 2

0

你可能得到了这个错误,对吧?

ERROR 1093 (HY000): You can't specify target table 'table_name' for update in FROM clause

解决此问题的最简单方法可能是将子计数选择到临时表中,然后加入该表以进行更新。

这应该可行,假设父/子关系的深度始终为 1。根据您的原始更新,这似乎是一个安全的假设。

我在表上添加了显式写锁,以确保在创建临时表后不会修改任何行。仅当您有能力在此更新期间将其锁定时才应执行此操作,这取决于数据量。

lock tables table_name write;

create temporary table temp_child_counts as
select parent_id, count(*) as child_count
from table_name 
group by parent_id;

alter table temp_child_counts add unique key (parent_id);

update table_name
inner join temp_child_counts on temp_child_counts.parent_id = table_name.id
set table_name.child_count = temp_child_counts.child_count;

unlock tables;
于 2010-06-16T18:37:18.800 回答
0

您的子选择更新应该可以工作;让我们试着修改一下:

UPDATE table_name
  SET children_count = (
    SELECT COUNT(sub_table_name.id) 
      FROM sub_table_name 
      WHERE sub_table_name.parent_id = table_name.id
  )

或者如果子表是同一张表:

UPDATE table_name as top_table
  SET children_count = (
    SELECT COUNT(sub_table.id) 
      FROM (select * from table_name) as sub_table
      WHERE sub_table.parent_id = top_table.id
  )

但我猜这不是超级有效。

于 2010-06-16T15:58:47.187 回答