MySQL подсчет таблицы внуков, возвращающих разные результаты
Я занимаюсь разработкой 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
Итак, если вы обратите свое внимание на общий подзапрос постов, приведенный выше, вы заметите, что я считаю все посты, где их идентификатор потока = идентификатор каждого потока, а затем = идентификатор каждого форума, если я использую этот запрос в одиночку (и включить псевдонимы таблиц, используемые в другом месте основного запроса), он работает отлично.
однако, когда используется в контексте основного запроса, а псевдонимы таблиц предоставляются в другом месте, он возвращает только счет для первой темы p/forum.
Если я пытаюсь указать псевдонимы таблицы в подзапросе, он возвращает ошибку, что было возвращено более одной строки.
Почему расхождение в содержании запроса, и почему подсчитывается только первый поток при использовании в качестве вычисляемого поля в основном запросе?
1 ответ
Так как 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
Этот запрос будет возвращать одну строку для каждого форума и должен правильно включать количество сообщений.
Обратите внимание, что если в форуме нет сообщений, этот форум не будет возвращен этим запросом - вы можете изменить его, используя ЛЕВЫЕ СОЕДИНЕНИЯ вместо СОЕДИНЕНИЙ, если вам нужно следить за этим.