现状
我的数据库中有两个表,一个用于帖子,一个用于评级。这些与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
,或者重新计算值,如果评级有一些较大的变化:例如禁止用户,这会导致删除该用户所做的所有评级。