计算用户帖子

时间:2014-05-14 20:30:21

标签: php mysql

我在用户页面上列出了标签/类别。我想显示用户为每个标签发布的帖子数量。标签,帖子和后标签位于不同的表格中。 困难在于,有两种帖子。帖子和评论。它们在同一个表中,但是类型不同。 “问题和答案”。答案中的related_id是与其相关的帖子的ID。

我试图以相当多的方式解决但却无法让它发挥作用。

我的数据库结构: 对于标签:

tagid      tag_name

对于帖子

id         type(enum:"question","answer")      related_id      user_id

对于后贴标签:

post_id    tag_id

我尝试的代码如下:

$user_active_query = mysql_query("select    p.id,
                                            p.user_id,
                                            pt.post_id,
                                            count(pt.post_id),
                                            pt.tag_id,
                                            t.tagid,
                                            t.tag_name
                                            from posts p
                                            inner join post_tags pt
                                            inner join tags t
                                            on p.id = pt.post_id
                                            and pt.tag_id = t.tagid
                                            where p.user_id = '$uid'
                                            group by t.tagid");
while($useractive = mysql_fetch_array($user_active_query)) {
    $user_active_counter = $useractive['count(pt.post_id)'];    
    echo "<a href='' class='btn btn-mini' style='margin:3px;'>".$useractive['tag_name']." (".$user_active_counter.")</a>";
}

页面上给出了用户ID。 “$ UID”。我只是厌倦了很多尝试并要求纠正。首先,它似乎是存储后标签的最佳方式,但现在这是一场噩梦。我的意思是,对我来说,用这种结构似乎不可能做到这一点。

3 个答案:

答案 0 :(得分:1)

你可以得到两个计数,即答案的数量和用户发布的问题,这里的诀窍也是使用正确的连接语法你缺少连接的on子句

SELECT 
  p.id,
  p.user_id,
  pt.post_id,
  COUNT(pt.post_id) all_posts,
  COALESCE(SUM(`type` = 'question')) questions,
  COALESCE(SUM(`type` = 'answer')) answers,
  pt.tag_id,
  t.tagid,
  t.tag_name 
FROM tags t 
  LEFT JOIN post_tags pt  ON(pt.tag_id = t.tagid)
  LEFT JOIN posts p   ON p.id = pt.post_id 
WHERE p.user_id = '$uid' 
GROUP BY t.tagid 

注意在mysql中加上一些表达式会产生一个布尔值

从评论中修改在上次加入时使用OR添加其他条件,因此第一个条件将加入与标记相关联的帖子,并且因为您的说明标记未直接与答案相关联但答案已关联他们的问题与相关的ID,所以可以加入标签ID的每个答案的相关ID,所以这种方式也可以得到答案的标签

SELECT 
  p.id,
  p.user_id,
  pt.post_id,
  COUNT(pt.post_id) all_posts,
  COALESCE(SUM(`type` = 'question')) questions,
  COALESCE(SUM(`type` = 'answer')) answers,
  pt.tag_id,
  t.tagid,
  t.tag_name 
FROM tags t 
  LEFT JOIN post_tags pt  ON(pt.tag_id = t.tagid)
  LEFT JOIN posts p   ON (p.id = pt.post_id OR p.related_id = pt.post_id)
WHERE p.user_id = '$uid' 
GROUP BY t.tagid 

答案 1 :(得分:0)

我认为你只需要在你的小组中加入p.type

$user_active_query = mysql_query("
        select 
        p.id,
        p.user_id,
        pt.post_id,
        count(pt.post_id),
        pt.tag_id,
        t.tagid,
        t.tag_name
        from posts p
        inner join post_tags pt
        inner join tags t
        on p.id = pt.post_id
        and pt.tag_id = t.tagid
        where p.user_id = '$uid'
        group by t.tagid, p.type"
    );

所以,我们也会对每种类型进行分组。

答案 2 :(得分:0)

我不确定我是否完全理解您的架构设计。但听起来你有两个加入&#34;路径&#34;,一个用于访问question类型的帖子,另一个用于转到子answer类型的帖子。

要获取与每个标记相关的question类型帖子(由特定用户)的计数,看起来就像到目前为止,基本上:

SELECT t.tagid
     , t.tag_name
     , COUNT(p.id) AS count_question
  FROM tags t
  JOIN post_tags pt
    ON pt.tag_id = t.tagid
  JOIN posts p
    ON p.id = pt.post_id
   AND p.type = 'question'
 WHERE p.user_id = '$uid'
 GROUP BY t.tagid

要获取与每个标记相关的问题相关的answer类型帖子(由特定用户),我们首先需要加入'question'(以获取标记) ,然后加入相关的答案。这与第一个查询几乎完全相同,只是我们将另一个连接添加到posts表以获取&#34; child&#34; answer - 输入帖子(因此我们可以计算answer类型的帖子),我们不会将question类型的帖子限制为来自特定用户的帖子...我们将根据用户提出的问题来计算用户发布的answer类型帖子。

SELECT t.tagid
     , t.tag_name
     , COUNT(a.id) AS count_answer
  FROM tags t
  JOIN post_tags pt
    ON pt.tag_id = t.tagid
  JOIN posts p
    ON p.id = pt.post_id
   AND p.type = 'question' 
  JOIN posts a
    ON a.related_id = p.id
   AND a.type = 'answer'
 WHERE a.user_id = '$uid'
 GROUP BY t.tagid

如果这些查询中的每一个都返回了您想要返回的总计数的一部分,那么这些可以合并,但它会有点混乱。

最直接的方法是将这两个结果与UNION ALL集合运算符组合,然后将其用作内联视图,即对组合结果集运行另一个查询。

例如:

SELECT r.tagid
     , r.tagname
     , SUM(r.count_post)                  AS count_total
     , SUM(IF(r.type='q',r.count_post,0)) AS count_question
     , SUM(IF(r.type='a',r.count_post,0)) AS count_answer
  FROM (
         SELECT 'q' AS type 
              , t.tagid
              , t.tag_name
              , COUNT(p.id) AS count_post
           FROM tags t
           JOIN post_tags pt
             ON pt.tag_id = t.tagid
           JOIN posts p
             ON p.id = pt.post_id
            AND p.type = 'question'
          WHERE p.user_id = '$uid'
          GROUP BY t.tagid

          UNION ALL

         SELECT 'a' AS type
              , t.tagid
              , t.tag_name
              , COUNT(a.id) AS count_post
           FROM tags t
           JOIN post_tags pt
             ON pt.tag_id = t.tagid
           JOIN posts p
             ON p.id = pt.post_id
            AND p.type = 'question' 
           JOIN posts a
             ON a.related_id = p.id
            AND a.type = 'answer'
           WHERE a.user_id = '$uid'
          GROUP BY t.tagid
       ) r
   GROUP BY r.tag_id

如果您对个别计数(问答类型帖子)不感兴趣,那么只需从外部查询的SELECT列表中删除这两个表达式,您也可以删除type =&#39 ; q&#39;,键入=&#39; a&#39;内联视图查询中的鉴别器列。

这不是结合结果的唯一方法,但我认为这是验证我们获得正确结果的最简单方法。结果(我们可以只运行内联视图查询并验证结果是否正确。


将它们组合起来的另一种方法更加混乱,更难以破译。

我们基本上需要加入question - 从所有用户输入帖子,然后对来自特定用户的answer类型帖子执行外部联接操作。

我们可以在WHERE子句中使用谓词来过滤掉行,这样只返回具有匹配的answer - 类型行-OR-的行是question - 类型的行。指定用户。

在SELECT列表中,我们需要进行一些额外的过滤,以便我们过滤掉其他用户的帖子。

这样的事情:

   SELECT t.tagid
        , t.tag_name
        , COUNT(DISTINCT IF(p.user_id='$uid',p.id,NULL))
          + COUNT(DISTINCT a.id)                         AS count_total
        , COUNT(DISTINCT IF(p.user_id='$uid',p.id,NULL)) AS count_question
        , COUNT(DISTINCT a.id)                           AS count_question
     FROM tags t
     JOIN post_tags pt
       ON pt.tag_id = t.tagid
     JOIN posts p
       ON p.id = pt.post_id
      AND p.type = 'question'
     LEFT
     JOIN posts a
       ON a.related_id = p.id
      AND a.type = 'answer'
      AND a.user_id = '$uid'
    WHERE p.user_id = '$uid'
       OR a.id IS NOT NULL
    GROUP BY t.tagid

但是,我并不喜欢这个问题,要弄清楚发生了什么事情太难了。我使用UNION ALL内联视图选择(上一个)查询。这更容易破译。