MySQL 统计返回不同结果的孙子表

发布于 2024-10-14 09:06:08 字数 1396 浏览 5 评论 0原文

我正在开发一个 PHP 论坛。 这个论坛使用了四个数据库表:forum、thread、post、user。

在我的登陆页面上,我列出了所有论坛,以及最新线程(通过联接和内部联接实现)、总线程(简单计数子查询)和帖子总数的列。

我有一个相当大小的查询,它返回上述所有内容,并且一切都运行得很好 - 除了帖子总数。

主要查询是这样的:

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 的计数。

如果我尝试在子查询中声明表别名,它会返回已返回多行的错误。

为什么查询内容存在差异,以及为什么在主查询中用作计算字段时仅计算第一个线程?

I am developing a PHP forum.
This forum uses four database tables: forum, thread, post, user.

On my landing page, I have a listing of all forums, plus columns for latest thread (achieved via join and inner join), total threas (simple count subquery), and total posts.

I have a fair-sized query that returns all of the above, and everything is working quite nicely - except for the total posts.

The main query is thus:

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

So, if you will direct your attention to the total posts subquery above
you'll notice htat I am counting all posts where their thread id = the id of each thread which then = the id of each forum, If i use this query alone (and include the table aliases used elsewhere in the main query) it works perfectly.

however, when used in the contect of the main query, and with tables aliases being provided elsewhere, it only returns the count for the first thread p/forum.

If i try to state the table aliases in the subquery it returns the error that more than one row has been returned.

Why the discrepancy regarding the content of the query, and why only the first thread being counted when used as a calculated field in the main query?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

逆蝶 2024-10-21 09:06:08

由于 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 来更改它。

As both t.forum_id and f.id are only relevant outside of the subquery, your subquery is equivalent to this:

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

You probably want something like this:

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

That query will return one row per forum, and should correctly include the post count.

Note that if there are no posts in a forum, that forum will not be returned by this query - you can change that by using LEFT JOINs instead of JOINs, if that is something you need to watch for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文