加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

php – 如何使用最少数量的查询获取帖子列表和关联的标签

发布时间:2020-12-13 16:57:42 所属栏目:PHP教程 来源:网络整理
导读:我的表格结构如下: TAGS(更多类别):id,标签名称,描述,slug 帖子:id,title,url …… POSTSTAGS:id,idPost,idTag 用户:id,username,userSlug … 投票:id,idUser 每个帖子最多可以有五个标签,每个用户只能投票一次.目前,由于标签尚未实现,我使用以下查询
我的表格结构如下:

TAGS(更多类别):id,标签名称,描述,slug

帖子:id,title,url ……

POSTSTAGS:id,idPost,idTag

用户:id,username,userSlug …

投票:id,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 to rescue).

下一步是在结果列表中包含标签,这里我结结巴巴.列表中的每个帖子都必须包含所有相关标签(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));

有没有更好或更快的方法来做到这一点?

解决方法

Is there any better or faster way to do this?

如果你通过postId索引$tagsResult,你可以使用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();
    }   
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读