我的表格结构如下:
TAGS(更多类别): ID,标记名称,描述,slug
帖子: id,title,url ...
POSTSTAGS: id,idPost,idTag
用户: id,username,userSlug ...
投票: id,idPost,idUser
每个帖子最多可以有五个标签,每个用户只能投票一次。目前,由于标签尚未实现,我使用以下查询检索我的分页结果集:
SELECT p.*, u.username, u.userSlug, u.id as userId,
exists (select 1 from votes v where v.idUser=$id AND p.userId=v.idUser AND p.url = v.url) as voted
FROM posts p
JOIN users u ON u.id=p.userId
ORDER BY p.created DESC
LIMIT 10 OFFSET :offset
查询通过PDO运行,并以JSON格式返回到angularjs ng-repeat
。 $id
是登录用户的ID。我在exists
子查询中使用它来在我的角度视图中使投票按钮变灰(在服务器端也有检查)。如果有人点击了视图中的用户名,他将进入详细信息页面,其中显示所有用户的帖子(userSlug
以进行救援)。
下一步是将标签包含在结果列表中,这里我结结巴巴。列表中的每个帖子都必须包含所有相关标签(tagName,description,slug),每个标签必须将您带到详细信息页面,其中显示该特定标签的所有相关帖子。
首先想到的解决方案是在运行前面提到的查询后强行执行此操作:
foreach ($postsResult as &$post) {
$sql ="SELECT t.* FROM tags t JOIN poststags pt ON t.id=pt.idTag WHERE pt.idPost=$post->id";
$stmt=$db->prepare($sql);
$stmt->execute();
$tagsResult=$stmt->fetchAll(PDO::FETCH_OBJ);
$post->tags = $tagsResult;
}
$response->write(json_encode($postsResult));
完成,轻松自在!很多查询会在服务器上产生巨大的压力。我们不想这样做。
第二个解决方案是触发另一个查询,该查询获取与postsResult相关联的所有标记,然后在每个帖子中插入相应的标记,让PHP执行脏工作。
$sql = "
SELECT t.*,
pt.idPost
FROM tags t JOIN poststags pt ON t.id=pt.idTag
WHERE pt.idPost IN (array of post ids)
";
$stmt=$db->prepare($sql);
$stmt->execute();
$tagsResult = $stmt->fetchAll(PDO::FETCH_OBJ);
foreach ($postsResult as &$post) {
$arr = array();
foreach ($tagsResult as $tag) {
if ($post->id==$tag->idPost) {
$arr[]=$tag;
}
}
$post->tags = $arr;
}
$response->write(json_encode($postsResult));
有更好或更快的方法吗?
答案 0 :(得分:3)
有更好或更快的方法吗?
如果您使用$tagsResult
postId
进行索引,可以使用FETCH_GROUP
进行索引,那么您可以删除内部嵌套循环并在常量时间内使用某个postId获取所有标记:
$sql = "
SELECT pt.idPost, — select idPost first so it’s grouped by this col
t.*
FROM tags t JOIN poststags pt ON t.id=pt.idTag
WHERE pt.idPost IN (array of post ids)
";
$stmt=$db->prepare($sql);
$stmt->execute();
$tagsResult = $smt->fetchAll(\PDO::FETCH_GROUP|\PDO::FETCH_OBJ);
//$tagsResult is now grouped by postId
//see https://stackoverflow.com/questions/5361716/is-there-a-way-to-fetch-associative-array-grouped-by-the-values-of-a-specified-c
foreach($postsResult as &$post) {
if(isset($tagsResult[$post->id])) {
$post->tags = $tagsResult[$post->id];
}
else {
$post->tags = array();
}
}