我正在开发一个PHP论坛。 该论坛使用四个数据库表:论坛,帖子,帖子,用户。
在我的目标网页上,我有一个所有论坛的列表,以及最新帖子的列(通过加入和内部联接实现),总威胁(简单计数子查询)和总帖子。
我有一个公平规模的查询,可以返回上述所有内容,而且一切都运行得非常好 - 除了总帖子。
主要查询是:
select f.id as forum_id,
f.name as forum_name,
f.description,
t.forum_id,
#this subquery counts total threads in each forum
(select count(t.forum_id)
from thread t
where t.forum_id = f.id
) as total_threads,
#this query counts total posts for each forum
(SELECT COUNT( p.id )
FROM post p
WHERE p.thread_id = t.id
AND t.forum_id = f.id
GROUP BY f.id) as total_posts,
t.id as thread_id,
t.name as thread_name,
t.forum_id as parent_forum,
t.user_id,
t.date_created,
u.id as user_id,
u.username
from forum f
# this join finds all latest threads of each forum
join
(select forum_id, max(date_created) as latest
from thread
group by forum_id) as d on d.forum_id = f.id
#and this inner join grabs the rest of the thread table for each latest thread
inner join thread as t
on d.forum_id = t.forum_id
and d.latest = t.date_created
join user as u on t.user_id = u.id
因此,如果您将注意力集中在上面的帖子子查询中 你会注意到htat我在计算他们的线程id =每个线程的id然后=每个论坛的id的所有帖子,如果我单独使用这个查询(并包括主查询中其他地方使用的表别名)它的工作原理完美。
但是,当在主查询的副本中使用,并且在别处提供表别名时,它只返回第一个线程p / forum的计数。
如果我尝试在子查询中声明表别名,则返回错误,即返回了多行。
为什么有关查询内容的差异,以及为什么在主查询中用作计算字段时只计算第一个线程?
答案 0 :(得分:0)
由于t.forum_id和f.id仅在子查询之外相关,因此子查询等效于此:
IF(t.forum_id = f.id,
(SELECT COUNT(p.id)
FROM post p
WHERE p.thread_id = t.id
GROUP BY 1)
, 0) AS total_posts
你可能想要这样的东西:
SELECT f.name AS forum_name, COUNT(p.id) AS total_posts
FROM forum AS f
JOIN thread AS t ON t.forum_id = f.id
JOIN post AS p ON p.thread_id = t.id
GROUP BY f.id
该查询将为每个论坛返回一行,并且应正确包含帖子计数。
请注意,如果论坛中没有帖子,此查询将不会返回该论坛 - 您可以使用LEFT JOIN而不是JOIN来更改该论坛,如果这是您需要注意的事项。