Нет необходимости в подзапросе. Движок не оценивает / не выполняет запрос в том же порядке, в котором вы пишете. Оптимизатор сгенерирует максимально оптимальный «путь выполнения» (хотя он не работает идеально). Однако для этого конкретного случая это задокументировано в Оптимизация предложения WHERE :
Для каждой таблицы в объединении создается более простой WHERE
, чтобы получить быструю WHERE
оценку для таблицу, а также пропустить строки как можно скорее.
Итак, ваше предположение:
I guess the WHERE filters the intermediate results after the LETF JOIN happens?
неверно. Учитывая индекс на posts.external_id
, движок будет только «касаться» соответствующей строки (строк) и выполнять соединение с posts_tags
только для этой / этих строк.
И по моему опыту я могу также сообщаю вам, что второй (тривиальный) запрос отлично подходит для производительности.
Я бы не стал использовать этот запрос по другой причине. Вы получаете дублирование данных поста для каждого связанного тега. Предположим, у вас есть сообщение, содержащее 10 КБ текста и 10 тегов. Вы получите 10 строк (по одной на тег) с одинаковым текстом и получите вместе 100 КБ данных. Затем вам нужно будет написать код для «дедупликации» данных.
Я бы предпочел выполнить два отдельных запроса:
SELECT posts.*
FROM posts
WHERE posts.external_id = ?
и
SELECT posts_tags.tag
FROM posts_tags
WHERE posts_tags.post_external_id = ?
и " объединить "результат в код приложения
или объединить теги с помощью GROUP_CONCAT ()
SELECT posts.*, GROUP_CONCAT(posts_tags.tag) as tags
FROM posts
LEFT JOIN posts_tags ON posts.external_id = posts_tags.post_external_id
WHERE posts.external_id = ?
GROUP BY posts.external_id
или с помощью JSON_ARRAYAGG ()
SELECT posts.*, JSON_ARRAYAGG(posts_tags.tag) as tags
FROM posts
LEFT JOIN posts_tags ON posts.external_id = posts_tags.post_external_id
WHERE posts.external_id = ?
GROUP BY posts.external_id
Анализ списка с разделителями-запятыми или JSON массив должен быть простым на любом языке приложения.