Reputation: 3024
I'm making an application that is similar to stackoverflow in that it has ratings for questions and answers and I also have tabs that show comments by oldest, newest and votes. I'm having trouble sorting by votes.
Here is my function:
/**
*
* @param int $threadid
* @param string $tab
* @param object $voting referencing Voting.class.php (may not be needed)
* @return database query/array
*/
public function getComments($threadid, $tab = 'oldest', $voting = null) {
if ($tab == 'oldest') {
$sql = "SELECT * FROM comments WHERE threadid = :threadid ORDER BY date ASC";
} else if ($tab == 'newest') {
$sql = "SELECT * FROM comments WHERE threadid = :threadid ORDER BY date DESC";
} else if ($tab == 'votes') {
//i dont know what to do here? read below for more explanation
} else {
$sql = "SELECT * FROM comments WHERE threadid = :threadid ORDER BY date ASC";
}
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':threadid', $threadid);
$stmt->execute();
$row = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $row;
}
Here is my database design:
**comments:** | id | userid | threadid | message | date |
**commentsrating:** | userid | commentid | voteup | votedown |
If ratings are in a separate table from comments is it possible to make a query for $tab == 'votes'
that will conform with the rest of the code?
and finally HTML:
<?php //Get comments
if (isset($_GET['tab'])) {
$getComments = $thread->getComments($threadid, $_GET['tab'], $voting);
} else {
$getComments = $thread->getComments($threadid);
} ?>
<?php for ($i = 0; $i < count($getComments); $i++) { ?>
<p>
<?php echo $getComments[$i]['message']; ?>
</p>
<p>
<span class="bid_votes_count" id="bid_votes_count<?php echo $getComments[$i]['id'] ?>">
<?php echo $voting->getEffectiveCommentVotes($getComments[$i]['id']) . " votes"; ?>
</span>
<span class="bid_vote_buttons" id="bid_vote_buttons<?php echo $getComments[$i]['id'] ?>">
<a href="javascript:;" class="bid_vote_up" id="<?php echo $getComments[$i]['id'] ?>"></a>
<a href="javascript:;" class="bid_vote_down" id="<?php echo $getComments[$i]['id'] ?>"></a>
</span>
</p>
<?php } ?>
Thanks in advance!
Upvotes: 3
Views: 361
Reputation: 1455
The fastest way would be storing a running tally of the votes as a field on the comments table (as mentioned in another answer). However you should also consider modifying the commentsrating table to make a little more sense and also help with the problem of tallying.
commentsrating: | userid | commentid | vote |
The reason you should only have vote is because a comment rating can only have a single vote. It can't be both an up AND down vote.
vote should be an int(1) +/-. eg. Can be 1 or -1 (or 0 theoretically). This way you can do the following SQL:
SELECT c.id, c.message, c.date, SUM(cr.vote) AS 'votes'
FROM `comments` c
JOIN `commentsrating` cr ON c.id=cr.commentid
WHERE c.threadid=':threadid'
GROUP BY c.id
ORDER BY `votes`
The query will take longer than an order by
total_votes field but this should be done anyway.
Upvotes: 2
Reputation: 107566
Give this a shot:
$sql = "SELECT * FROM comments c JOIN (SELECT commentid, ".
"(SUM(voteup) - SUM(votedown)) votes, " .
"FROM commentsrating GROUP BY commentid) i ON " .
"c.id = i.commentid WHERE c.threadid = :threadid " .
"ORDER BY i.votes DESC";
Obviously not the best performance with the crazy JOIN, but should get you to "it works," after which you can worry about performance.
Upvotes: 1
Reputation: 324750
SELECT * FROM `comments` WHERE `threadid`=:threadid ORDER BY (SELECT `voteup`-`votedown` FROM `commentsrating` WHERE `commentid`=`comments`.`id`) DESC
Try that?
Upvotes: 0
Reputation: 255005
Add rating
field to the comments
table and maintain it manually or with trigger on commentsrating
table.
Obviously, put there pre-calculated value of the rating and now you are able to have a simple and terrible fast question to perform.
Upvotes: 3