现在的情况
我的数据库中有两个表,一个表用于帖子,一个表用于评级。这些链接与MySQL中的一个关系链接,因此一个帖子可能具有0、1或多个评分,但一个评分只能应用于一个帖子。
当我获取帖子列表时,我也希望获得评分,但不必在foreach循环中为每个帖子分别对数据库进行调用。
为此,我尝试使用SQL查询来获取所有具有等级LEFT JOIN的帖子,以使其返回如下结果:
statusId|statusBody|rating
-----------------------------
1, post1, 0
1, post1, 1
2, post2, 0
3, post3, 1
3, post3, 1
SQL工作正常,并且我得到了我想要的数据。
理想情况下,我现在想要实现的是将这张表变成一个对象集合,每个对象都存储帖子信息以及一个取决于其总评分的值。
使用PDO返回数据结果后,这是我用来映射数据的代码:
代码逻辑
我的代码的逻辑如下:
Get all statuses joined with ratings table
Create empty output array
Loop through PDO result
{
Create loop specific temp array
Push first row of result into temp array
Remove row from PDO result
Loop through PDO result for objects with matching statusId
{
If row matches statusId, add to temp buffer and remove from PDO result
}
Take first row of buffer and create status object
Loop through objects in temp array to calculate ratings and add onto above status object
Clear temp buffer
Add status object to output array
}
return output array
实际代码
try
{
$result = $pdo->query($sql);
//if($result == false) return false;
$statuses = $result->fetchAll(PDO::FETCH_CLASS, 'status');
}
catch (PDOException $e)
{
return FALSE;
}
if (!$result) {
return FALSE;
}
//create empty output array to be filled up
$status_output = array();
//loop through all status
foreach($statuses as $s1key => $s1value)
{
//initialise temporary array;
$status_temp_buffer = array();
//create temp array for storing status with same ID in and add first row
array_push($status_temp_buffer, $s1value);
//remove from primary array
unset($statuses[$s1key]);
//loop through array for matching entries
foreach($statuses as $s2key => $s2value)
{
//if statusId matches original, add to array;
if($s2value->statusId == $s1value->statusId)
{
//add status to temp array
array_push($status_temp_buffer, $s2value);
//remove from primary array
unset($statuses[$s2key]);
}
//stop foreach if statusId can no longer be found
break;
}
//create new status object from data;
$statObj = $status_temp_buffer[0];
//loop through temp array to get all ratings
foreach($status_temp_buffer as $sr)
{
//check if status has a rating
if($sr->rating != NULL)
{
//if rating is positive...
if($sr->rating == 1)
{
//add one point to positive ratings
$statObj->totalPositiveRatings++;
}
//regardless add one point to total ratings
$statObj->totalAllRatings++;
}
}
//clear temporary array
$status_temp_buffer = NULL;
//add object to output array
array_push($status_output, $statObj);
}
问题
我用此代码遇到的问题是,尽管评分很好,并且可以正确计算每个帖子的评分总数,但是在帖子具有多个评分的地方,它仍会显示重复项。
任何帮助,将不胜感激,
谢谢
据我了解,目标是获得每个Post条目的总评分。除了手动遍历每个等级之外,您还可以采取其他两种方法:
计算查询中的总数:
SELECT SUM(rating) AS total , .. FROM Posts LEFT JOIN .... GROUP BY statusID
您将收到一个Post条目列表,每个条目已经计算出总评分。如果您对Ratings表有很多writes,而reads少得多,那么这是一个很好的解决方案。
另一种方法是打破表规范化,但要提高read性能。您需要做的是在Posts表中添加另一列:total_rating。并且在Ratings表中的INSERT上有一个TRIGGER,它会相应地更改Posts.total_rating。
这种方式的好处是简化了Posts的请求。同时,Ratings表现在可以用于确保total_rating的计算正确,或者如果评级有较大变化,则可以重新计算值:例如禁止用户,这会导致删除所有评级由该用户制作。