MySql将表中的子查询计数相关联

时间:2011-07-14 23:28:26

标签: mysql

我有3个与以下字段相关的表格:

forums          topics          posts
    f_id ---- f_id  t_id ---- t_id  p_id    

对于给定的f_id我在1个查询中尝试2个不同的计数:

  1. t_id(主题)
  2. 的总数
  3. p_id(帖子)
  4. 的总数

    例如f_id=78应该只是

    tc  |  pc
    ---------
    4   |  3
    

    意味着在这个论坛中有4个主题和总共3个帖子。但是,当我使用这个简单的查询(经过几个小时的尝试和研究我的最佳尝试)后:

    SELECT (
    SELECT COUNT( t_id ) 
    FROM topics
    WHERE f_id =  '78'
    ) AS tc, (
    
    SELECT COUNT( p_id ) 
    FROM posts
    WHERE posts.t_id = topics.t_id
    ) AS pc
    FROM topics
    WHERE topics.f_id =  '78'
    

    但这只会导致与f_id匹配的主题中每一行的计数如下:

    tc  |  pc
    ---------
    4   |  0
    4   |  1
    4   |  2
    4   |  0
    

    而不是总数。我真的被困在这里,尽管我很确定这不是一件难事。谢谢!


    编辑:根据要求提供一些样本数据:

    论坛

    f_id  t_name      ...
    ---------------------
    78    Test        ...
    33    Something   ...
    

    主题

    f_id  t_id   t_date      ...
    ----------------------------
    78    28     2011-07-14  ...
    78    53     2011-07-14  ...
    78    54     2011-07-14  ...
    78    56     2011-07-14  ...
    33    57     2011-07-14  ...
    

    帖子

    t_id  p_id  p_date      ...
    ---------------------------
    54    2     2011-07-14  ...
    54    4     2011-07-14  ...
    53    5     2011-07-14  ...
    

3 个答案:

答案 0 :(得分:0)

使用count(distinct column)计算列的different值的数量:

select
    f.f_id,
    count(distinct t.t_id) as tc,
    count(distinct p.p_id) as pc
from forums f
join topics t on t.f_id = f.f_id
join posts p on p.t_id = t.t_id
group by f.f_id;  -- edited. initial answer had this group by omitted

答案 1 :(得分:0)

通常会直接在主题和论坛表中存储帖子和帖子的预先计算值,因为计数(可能是区别的)并不是一个便宜的操作。

创建后,您可以使用触发器或代码维护该计数器。

答案 2 :(得分:0)

我似乎找到了以下解决方案,它实际上将@Bohemian的查询与原始查询混合在一起,似乎效果很好。我不确定这是否是实现的最佳方式。

SELECT f.f_id, (SELECT COUNT(t.t_id) 
                FROM topics t
                WHERE t.f_id =  f.f_id) AS tc, 

                COUNT(distinct p.p_id) AS pc

FROM forums f
JOIN topics t ON t.f_id = f.f_id
JOIN posts p ON p.t_id = t.t_id

WHERE f.f_id = 78
GROUP BY f.f_id;