php - 如何获取查询次数最少的帖子列表和关联的标签

标签 php mysql sql angularjs

我的表格结构如下:

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

POSTS: id, title, url ...

POSTSTAGS:id、idPost、idTag

用户:id、用户名、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 子查询中使用它来使 Angular View 中的投票按钮变灰(服务器端也有检查)。如果有人在 View 中单击用户名,他将被带到显示所有用户帖子的详细信息页面(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(s) 关联的所有标签,然后在每个帖子中插入相应的标签,让 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();
    }   
}

关于php - 如何获取查询次数最少的帖子列表和关联的标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32037600/

相关文章:

MySQL 使用子查询获取表名?

php - 获取同一列上具有不同数据的行

sql - 使用 CTE 拆分表中的行

php - MySQL PHP插入两个表事务

javascript - 将 javascript 变量打印为 html 标签中的属性

php - 将 SQL 查询列传递到另一个 .php 页面

mysql - 分享mysql数据库

mysql - Python 3 pymysql 数据库访问 - 连接到数据库出现以下错误

PHP 到 XML foreach 从 mySQL

javascript - 限制段落字符的有效方法(垂直文本溢出)