简体   繁体   English

在子查询中使用SUM优化MySQL查询

[英]Optimising a MySQL query with a SUM in the sub-query

I'm trying to do a very specific thing in WordPress: expire posts over 30 days old that have no "likes" (or negative "likes") based on someone else's plugin. 我正在尝试在WordPress中做一个非常具体的事情:过期超过30天的帖子因其他人的插件而没有“赞”(或否定“赞”)。 That plugin stores individual likes/dislikes for each user/post in a separate table (+1/-1), which means that my selection criteria are complex, based on a SUM. 该插件在一个单独的表(+ 1 / -1)中存储每个用户/帖子的个人喜欢/不喜欢,这意味着基于SUM,我的选择标准很复杂。

Doing the SELECT is easy, as it is a simple JOIN on post ID with a "HAVING" clause to detect the total likes value of more than zero. 进行SELECT很容易,因为它是帖子ID上的简单JOIN,带有“ HAVING”子句,可以检测总点赞值大于零。 It looks like this (with all the table names simplified for readability): 看起来像这样(为了便于阅读,简化了所有表名):

SELECT posts.id, SUM( wti_like_post.value )
FROM posts
JOIN wti_like_post
ON posts.ID = wti_like_post.post_id
WHERE posts.post_date < DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY posts.ID
HAVING SUM( wti_like_post.value ) < 1

But I'm stuck on optimising the UPDATE query. 但是我一直坚持优化UPDATE查询。 The unoptimised version takes 2 minutes to run, which is unacceptable. 未经优化的版本需要2分钟才能运行,这是不可接受的。

UPDATE posts
SET posts.post_status = 'trash'
WHERE posts.post_status = 'publish'
AND posts.post_type = 'post'
AND posts.post_date < DATE_SUB(NOW(), INTERVAL 30 DAY)
AND ID IN
(SELECT post_id FROM wti_like_posts
 GROUP BY post_id
 HAVING SUM( wti_like_post.value ) < 1 )

This is obviously because of my inability to create an UPDATE query with a join based on a SUM result - I simply don't know how to do that (believe me, I've tried!). 显然这是因为我无法基于SUM结果创建带有联接的UPDATE查询-我根本不知道该怎么做(相信我,我已经尝试过!)。

If anyone could optimise that UPDATE for me, I'd be terribly grateful. 如果有人可以为我优化该UPDATE,我将非常感激。 It'd also teach me how to do it properly, which would be neat! 它还会教我如何正确地做,这将很整洁!

Thanks in advance. 提前致谢。

Well it also depends on the no. 好吧,这还取决于否。 of posts and also in subquery it will SUM the post ids which were trashed also there should be filter in the subquery rather than your update query try this one 帖子以及在子查询这将总结这也被捣毁后IDS应该在子查询过滤器,而不是你的更新查询,试试这个

UPDATE posts
SET posts.post_status = 'trash'
WHERE ID IN
(
SELECT posts.id
FROM posts
INNER JOIN wti_like_post
ON (posts.ID = wti_like_post.post_id AND  posts.post_status = 'publish'
AND posts.post_type = 'post')
WHERE posts.post_date < DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY posts.ID
HAVING SUM( wti_like_post.value ) < 1    
 )

Well maybe sounds stupid but you could create a table out of the select, place an Index on it and then simply use the standard JOIN for update on that new table. 好吧,这听起来可能很愚蠢,但是您可以从选择中创建一个表,在其上放置一个索引,然后简单地使用标准JOIN对该新表进行更新。

I guess even if you do that always on the fly, it should be faster then the non-indexed version. 我想,即使您总是即时执行此操作,它也应该比非索引版本更快。

EDIT: Here is the code, sry it's out of my head haven't checked if it passes but it should give you at least an idea what I mean. 编辑:这是代码,对不起,我没检查过它是否通过,但是它至少应该使您明白我的意思。

CREATE TABLE joinHelper(
  id INT NOT NULL,
  PRIMARY KEY ( id )
);
INSERT INTO joinHelper(id)
SELECT post_id FROM wti_like_posts
GROUP BY post_id
HAVING SUM( wti_like_post.value ) < 1

UPDATE posts JOIN joinHelper ON (posts.ID = joinHelper.id)
SET posts.post_status = 'trash'
WHERE posts.post_status = 'publish'
AND posts.post_type = 'post'
AND posts.post_date < DATE_SUB(NOW(), INTERVAL 30 DAY)

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

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