我有两张桌子。一个是带有帖子的制作表,另一个是帖子视图的集合。
每小时一次,所有帖子视图都会组合在一起,主要生产表会更新。并且帖子的观看表被截断了。
我的目标是将此功能转换为纯SQL,因此我可以将其作为预定事件在数据库引擎内运行。
SQL是我最薄弱的一点,我可以使用SELECT在一个UPDATE中。但如果有两个UPDATE查询,那么我需要某种变量。
这是我开始的地方:
<?
# find new views grouped together:
$find_views = db::query("SELECT `post_id`, COUNT(*) AS `post_views` FROM `posts__views` WHERE `date_imported` IS NULL GROUP BY `post_id`;");
while ($view = db::fetch($find_views)) {
# Update the main production tables views_count column:
db::query("UPDATE `posts` SET `views_count` = views_count + {$view['post_views']} WHERE `id` = '{$view['post_id']}';");
# Update the post's views table... but why does it actually needs this update hmm..
db::query("UPDATE `posts__views` SET `date_imported` = NOW() WHERE `date_imported` IS NULL AND `post_id` = '{$view['post_id']}';");
}
# Trunkate post's views:
db::query("TRUNCATE TABLE `posts__views`;");
我意识到,通过删除第二个UPDATE,我可以立即优化代码。我想我也可以完全删除date_imported,因为所有视图都会被解析然后被截断。
这意味着,我很可能会UPDATE ... WHERE (SELECT ...)
。唯一的问题是,我知道如何在其中使用SELECT进行UPDATE,一个变量。但由于我在同一个UPDATE查询中有$view['post_views']
和$view['post_id']
,所以我无可救药。
修改
这与以下内容不重复:
MySQL: UPDATE table with COUNT from another table?
因为那里没有截断。它的工作原理是,视图表保持原样,每次都使用旧视图进行计算。我截断了表,因此主表中没有新视图的行被设置为0。
编辑2
所以我已经走到了这一步:
UPDATE `posts` SET `views_count` = views_count + (SELECT COUNT(`id`) AS `views` FROM `posts__views` WHERE `post_id` = `posts`.`id` GROUP BY `post_id` HAVING COUNT(`id`) > 0)
不,谢谢你将此问题标记为重复。因为我找不到任何方法来确保,没有视图的其他行不会被设置为0.所以innner-SELECT应该出来,而外部UPDATE应该有WHERE子句。理论上就是这样(但这根本没有看起来优化):
UPDATE `posts` SET `views_count` = views_count + (SELECT COUNT(`id`) AS `views` FROM `posts__views` WHERE `post_id` = `posts`.`id` GROUP BY `post_id` HAVING COUNT(`id`) > 0) WHERE (SELECT COUNT(`id`) AS `views` FROM `posts__views` WHERE `post_id` = `posts`.`id` GROUP BY `post_id` HAVING COUNT(`id`) > 0) > 0;