4 из подзапросов были просто для извлечения агрегатов для разных столбцов в одной таблице (s_user_votes
), поэтому их было легко объединить в один join
.
Я использовал left [outer] join
, чтобы исходная семантика была сохранена (если у истории нет голосов пользователей, она все равно должна появиться в результатах).
Другой подзапрос находится в другой таблице (s_comments
).Я поместил это в производную таблицу, а не соединял ее непосредственно, чтобы гарантировать, что возвращается не более 1 строки на историю.
Это предотвратит проблему, когда история с несколькими комментариями или несколькими пользовательскими голосами вызоветумножение количества возвращаемых строк, испорченное вычислением SUM
.
Я также добавил GROUP BY
к истории id
(В MySQL этого достаточно, чтобы другие СУБД требовали, чтобы вы перечислили все неагрегированные столбцы)
select s.id,
s.user_id,
m.photo as profile_photo,
CONCAT(m.name, ' ', m.lastname) as fullname,
s.title,
s.date,
s.photo,
s.city,
c.comments_sum,
SUM(v.important) as v_important,
SUM(v.fun) as v_fun,
SUM(v.interesting) as v_interesting,
SUM(v.boring) as v_boring
from stories as s
join members as m
on s.user_id = m.id
left join (select story_id,
count(story_id) as comments_sum
from s_comments
group by story_id) as c /*<-- Can't remember if "as" needed here in MySQL*/
on c.story_id = s.id
left join s_user_votes as v
on v.story_id = s.id
group by s.id
order by v_interesting desc,
v_boring asc,
s.date desc
limit 50;