网站MySQL评论系统

3
我需要帮助处理一个涉及评论系统的查询,该查询使用以下两个表进行设置。
reviews ------- id 日期 user_id item_id rating review 1 02-2012 40 456 3 '我喜欢它' 2 03-2012 22 342 1 '我不喜欢它' 3 04-2012 45 548 0 '我讨厌它'
reviews_thumbs -------------- review_id user_id like 1 22 1 1 45 -1 2 40 -1 3 22 1
“reviews_thumbs”表用于跟踪评论的赞和踩,以便可以根据质量对评论进行评分。在“like”列中,1表示赞,-1表示踩。(reviews表中的“rating”列是星级系统,与此无关。)
在加载评论时,我需要以这样一种方式连接reviews_thumbs表,以便我知道以下细节(对于返回的每个单独的评论):
1.赞的总数 2.踩的总数 3.当前活动用户是否点赞或点踩了评论
我使用以下查询成功实现了这一点,但我感觉不太对:
SELECT `reviews`.*, COUNT(upVoteTable.`user_id`) AS upVotes, COUNT(downVoteTable.`user_id`) AS downVotes, COUNT(userUpTable.`user_id`) AS userUp, COUNT(userDownTable.`user_id`) as userDown
FROM `reviews`
LEFT JOIN `reviews_thumbs` AS upVoteTable ON upVoteTable.`review_id` = `reviews`.`id` AND upVoteTable.`like` = 1
LEFT JOIN `reviews_thumbs` AS downVoteTable ON downVoteTable.`review_id` = `reviews`.`id` AND downVoteTable.`like` = -1
LEFT JOIN `reviews_thumbs` AS userUpTable ON userUpTable.`review_id` = `reviews`.`id` AND userUpTable.`like` = 1 AND userUpTable.`user_id` = :userid
LEFT JOIN `reviews_thumbs` AS userDownTable ON userDownTable.`review_id` = `reviews`.`id` AND userDownTable.`like` = -1 AND userDownTable.`user_id` = :userid
WHERE `item_id`=:itemid
GROUP BY `reviews`.`id`
ORDER BY `date` DESC
(并绑定适当的:userid和:itemid。)
这个查询完美地实现了我的目标,但是涉及到很多JOIN操作,我几乎肯定有更好的方法来完成它,但我似乎无法想出任何其他的方法。
请问是否有人可以指导一下如何以更简洁的方式实现这个查询?
我尝试过使用GROUP_CONCAT来列出一个包含所有用户ID和点赞信息的字符串,然后运行正则表达式来查找用户ID以查看他们是否对评论进行了投票,但这种方法感觉非常不干净。谢谢您提供的任何帮助。

不要在大型网站上使用JOIN。当您拥有超过2个服务器时,这将导致您需要重写大量代码。 - TheJSB
3
不要计算赞成票和反对票,考虑使用整数投票列,-1表示反对票,+1表示赞成票,这样可以轻松地进行“SUM”操作以获得总分。另外,在请求现有查询的改进时,如果您可以在SQLFiddle上提供示例,那么将非常有帮助——您可以在那里设置架构和数据,这样做可能会促使人们参与并改进它。 - halfer
@halfer,关于投票的想法很好,谢谢你。至于Fiddle,我认为它在这里并不重要,因为这只是一个有关最佳实践的开放性问题。这些左连接并不像最佳实践解决方案,它们感觉过度复杂,我只是在寻求指导,而不是让别人替我编写代码。谢谢! - Leng
2个回答

1
您可以修改reviews_thumbs,使其看起来更像这样:
reviews_thumbs
--------------
review_id   user_id upvote downvote
1           22      1      0
1           45      0      1
2           40      0      1
3           22      1      0

这将有效地存储重复信息,但当你有一个好的目的时,这是可以接受的。你真正想知道两件事情,这给了你一个快速的总和在2列(以及这些结果的快速减法),以获得你正在寻找的确切答案。这将使你只需查询reviews_thumbs表两次,一次为总数,一次为用户特定操作。

这是一个优雅、出色的解决方案,将我的系统性能提升了一倍。非常感谢您抽出时间来帮助我! :) - Leng
2
不用谢,这只是我回报 Stack Overflow 多年来给予我的所有帮助。 - invertedSpear

0

不确定这是否会提高您的查询性能,但您可以尝试在子选择中进行计数

SELECT `reviews`.*,
(SELECT count(*) FROM reviews_thumbs t WHERE t.review_id =reviews.id AND t.like = 1) AS upVotes
...
FROM reviews
...  

谢谢您的回复,Simon。不幸的是,您说得对,这种子查询风格并不能提高性能,因为reviews_thumbs仍需要被查询4次。 - Leng

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接