MySql correlated subquery count across tables
I have 3 tables that are related with the fields below:
forums topics posts
f_id ---- f_id t_id ---- t_id p_id
For a given f_id
I'm trying to 2 different counts in 1 query:
- the total numbers of
t_id
(topics) - the total numbers of
p_id
(posts)
for example f_id=78
should simply result to
tc | pc
---------
4 | 3
Meaning there are 4 topics and a total of 3 post to those topics, all in that forum. But when I use this simple query (which is after hours of trying and research my best attempt):
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 to开发者_如何转开发pics
WHERE topics.f_id = '78'
But this only results to a count for each row in topics that matches the f_id
like this:
tc | pc
---------
4 | 0
4 | 1
4 | 2
4 | 0
and not a total count. I'm genuinely stuck here, even though I was pretty sure this was not a hard thing to achieve. Thanks!
Edit: as requested a bit of sample data:
forums
f_id t_name ...
---------------------
78 Test ...
33 Something ...
topics
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 ...
posts
t_id p_id p_date ...
---------------------------
54 2 2011-07-14 ...
54 4 2011-07-14 ...
53 5 2011-07-14 ...
It is common to store precalculated values of posts and threads directly in topics and forums tables accordingly, since counting (probably with distinction) is not a cheap operation.
After creating you can maintain that counters with triggers or your code.
Use count(distinct column)
to count the number of different
values for a column:
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
I seem to have found the following solution that actually mixes both @Bohemian 's query with my original one and seems to work well. I'm not sure if this is the optimal way to achieve though.
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;
精彩评论