为了修复错误,我必须遍历表中的所有行,将缓存的子计数更新为其实际值。表中的东西的结构形成一棵树。
在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
)
除了以上不起作用(我明白为什么不行)。
答案 0 :(得分: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
)
但我猜测这不是超级高效。
答案 1 :(得分: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;