MYSQL, Единый запрос и все, все, все
Не сомневаюсь, что среди здешних пользователей есть профи SQL, поэтому хочу спросить следующее: можно ли получить несколько разных SELECT одним запросом?
Есть следующий SELECT:
SELECT `ID`, `Teamname`, `User`, `Date_made` FROM `Team`
В ответ я получаю:
ID Teamname User Date_made
1 Sire 1 2020-02-20 18:28:46
2 Rulyatki 1 2020-03-03 16:07:38
И другой SELECT:
SELECT `ID`, `User`, `Book`, `Message`, `Date_pub` FROM `Comment`
Ответ:
ID User Book Message Date_pub
1 1 2 фывфыв 2020-02-22 15:57:42
В php это выглядит так:
[0] => [
'ID' => '1',
'Teamname' => 'Sire',
'User' => '1',
'Date_made' => '2020-02-20 18:28:46'
],
[1] => [
'ID' => '2',
'Teamname' => 'Rulyatki',
'User' => '1',
'Date_made' => '2020-03-03 16:07:38'
]
И
[0] => [
'ID' => '1',
'User' => 'Sire',
'Book' => '1',
'Message' => 'фывфыв',
'Date_pub' => '2020-02-22 15:57:42'
]
Так что же я должен отправить на сервер, чтобы в ответ получить массив такого типа:
[0] => [ <----- Здесь ответ из первого SELECT
[0] => [
'ID' => '1',
'Teamname' => 'Sire',
'User' => '1',
'Date_made' => '2020-02-20 18:28:46'
],
[1] => [
'ID' => '2',
'Teamname' => 'Rulyatki',
'User' => '1',
'Date_made' => '2020-03-03 16:07:38'
]
],
[1] => [ <----- Здесь ответ из второго SELECT
[0] => [
'ID' => '1',
'User' => 'Sire',
'Book' => '1',
'Message' => 'фывфыв',
'Date_pub' => '2020-02-22 15:57:42'
]
]
Зачем мне это? Я часто слышу от программистов, что нужно делать оптимизированные запросы и мне эта идея нравится, но на практике я столкнулся с проблемой. Все знают, что на главной странице сайта нужно выводить какую-нибудь актуальную информацию (последние комментарии, новости, и т.п.). Сейчас я делаю это так: SELECT для комментариев, SELECT для новостей, SELECT для рекомендация, SELECT для рекламы. В итоге выходит много SELECT'ов, что мне не нравится. Поэтому я и задался вопросом, можно ли это сделать одним разом И есть ли в этом смысл? Будет ли это работать быстрее?
Заранее извиняюсь, если вопрос тупой, но я лично не понимаю, что делать.
Ответы (2 шт):
Точно так, как описано, сделать НЕВОЗМОЖНО. Причина - возвращаемый набор записей имеет строго определённую структуру, единую для всех записей набора.
В рамках заявленного сервера БД возможны минимум два решения, похожих на требуемое.
Решение 1 - мультизапрос. Т.е. два запроса, разделённые штатным символом окончания текста запроса ;, отправляются на сервер как один запрос, и в ответ возвращается два набора данных как единый массив/коллекция. Т.е. возвращаемые набор имеет два (или более) вложенных элемента, каждый из которых является самостоятельным набором данных, со своей структурой.
Формализованный пример:
result=connection.query("select id,val from t1; select id,txt,cnt from t2;")
Результат будет достаточно близок к структуре, показанной в вопросе.
Решение 2 - синхронизация ("выравнивание") структур выходных данных и использование UNION ALL. Недостающие поля вводятся дополнительно в структуру отдельных запросов с соблюдением типа данных, и им присваивается некое константное значение (обычно NULL, но возможны также ноль, пустая строка или, скажем, литерал 'EMPTY'). Обычно также вводится дополнительное поле, значение которого позволяет установить, к какому из объединённых наборов относится каждая конкретная запись, если это нельзя выяснить анализом значений полей, объявленных в исходных данных как NOT NULL или имеющих фиксированный непересекающийся набор значений.
Формализованный пример:
result=connection.query("select id, val , CAST(null AS CHAR) as txt, 0 as cnt from t1
union all
select id, null, txt , cnt from t2;")
либо
result=connection.query("select '1' as setnum, id, val , CAST(null AS CHAR) as txt, 0 as cnt from t1
union all
select '2' , id, null, txt , cnt from t2;")
Этот мой ответ адресован в первую очередь не автору вопроса, а отвечателям, завсегдатаям этого сайта.
Я уже много лет наблюдаю нездоровую тенденцию: ответить на поставленный вопрос любой ценой. Порвать заднюю часть тела в лоскуты, презреть здравый смысл и формальную логику, но в муках родить ответ - каким бы бессмысленным он не был.
Такое ощущение, что люди воспринимают вопрос не как практическую задачу, а как персональное тестовое задание адресованное лично им. Или, я не знаю - как испытание, в котором за отрицательный ответ полагается смертная казнь. И с энтузиазмом принимаются строчить ответ.
В итоге вместо реальной помощи автор вопроса получает искусственного кадавра, уродливого монстра, который абсолютно нежизнеспособен, а - главное - решает несуществующую задачу.
У меня большая просьба к любителям отвечать: проводить минимальный аудит вопроса, оценивать его осмысленность. И не стесняться давать отрицательный ответ. Нет ничего плохого или постыдного в том, что на вопрос "как мне из 2х2 получить 5" ответить "никак". И рассказать что правильный ответ - 4.
Если человек боится выполнения 5 простых запросов на одной странице, то надо не кидаться удовлетворять его фантазии, продиктованные недостатком знаний и опыта. А объяснить, что главное не количество, а качество запросов. И оптимизировать надо не количество, а качество. Сам по себе запрос в базу данных - очень простая операция. БД не кирпичи таскает чтобы ответить на запрос. Бояться запросов не надо. Без нужды плодить запросы, разумеется, не стоит, но и бояться запроса, который трубется для получения информации, и является оптимальным с точки зрения производительности, абсолютно не стоит.
Я часто слышу от программистов, что нужно делать оптимизированные запросы
Речь идет об оптимизации одного запроса, а не о запихивании 10 запросов в один. Быстрее они от этого выполняться не станут. Если среди этих десяти есть один медленный, то как бы ты их не рассаживал, в итоге страница всё равно будет грузиться медленно. И чтобы она грузилась быстро, надо оптимизировать медленный запрос, а не искать способ ускорить то, что и так работает быстро.