Вот моя проблема: получение результатов запроса из двух таблиц db, даже если вторая таблица не имеет соответствующих записей.
Вот пример кода, который я использую в SQL
SELECT DISTINCT apps.id, apps.*, req.status FROM applications AS apps, requests AS req WHERE apps.id = {$app_id}
Но проблема в том, что он не потянет приложения, у которых нет значения request.status / entry, так что вопросы: будет ли возможно изменить этот простой запрос, чтобы поднять результаты для всех приложений. * Строки, даже если там нет соответствующих запросов. Строка / запись?
EDIT BELLOW:
так вот мой новый запрос от обратной связи, которую я получил (это прекрасно работает)
SELECT DISTINCT apps.*, req.status FROM applications AS apps LEFT JOIN requests AS req ON (req.app_id = apps.id AND req.uid = {$user_id}) WHERE apps.id = {$app_id}
BUT: Когда я добавляю новое выражение в предложение where для фильтрации статуса запроса, я получаю ту же проблему, что и с неявным запросом, я не получаю результаты (запрос ниже)
SELECT DISTINCT apps.*, req.status FROM applications AS apps LEFT JOIN requests AS req ON (req.app_id = apps.id AND req.uid = {$user_id}) WHERE apps.id = {$app_id} AND (req.status = 2 OR req.status = 5)
ДРУГОЕ ИЗМЕНЕНИЕ
Вот обновленный код для просмотра. Теперь проблема заключается в том, что если я добавлю подзапрос, суб-запрос вытащит все строки, тогда значение NULL будет как значение для столбца состояния, но как только я добавлю состояние WHERE! = 2, он просто удалит все записи, не должно ли это иметь все строки с нулевым значением? потому что null явно! = 2.
SELECT DISTINCT apps . * FROM (SELECT apps . *, req.status FROM appstore_app AS apps LEFT JOIN app_user_request AS req ON (req.uid = 187 AND req.appid = apps.appid) WHERE apps.appid > 0 AND apps.company_id = 122) AS apps WHERE apps.status != 2 ORDER BY apps.average_user_rating DESC
ЗАВЕРШЕНИЕ
СПАСИБО ЗА ПОМОЩЬ!
Вот мой последний запрос, который работал для меня:
SELECT apps.*, req.status FROM appstore_app AS apps LEFT JOIN app_user_request AS req ON (req.uid = {$user_id} AND req.appid = apps.appid AND (req.status IS NULL OR req.status != 2)) WHERE apps.appid > 0 AND apps.company_id = {$company_id}
ОП сказал:
BUT: Когда я добавляю новое выражение в предложение where для фильтрации статуса запроса, i> получаю ту же проблему, что и при неявном запросе, я не получаю результаты (запрос ниже)
SELECT DISTINCT apps.*, req.status FROM applications apps LEFT JOIN requests req ON req.app_id = apps.id AND req.uid = {$user_id} WHERE apps.id = {$app_id} AND ( req.status = 2 OR req.status = 5 )
Проблема заключается в том, что предложение where
фильтрует результаты, поэтому ваш тест на req.status
из 2 или 5 выдает все, где req.status
имеет значение null, потому что ни одна строка не соответствует табличным applications
.
Общий, теоретический (поскольку ничто, кроме тривиальной реализации, никогда не будет делать что-либо подобное) порядок операций для оператора select
:
from
. join
и исключив строки, которые не проходят указанные тесты. where
, удалив строки, которые не проходят указанные тесты. group by
, и разделите результаты, заданные на группы. select
операторов. order by
. Вы можете сделать одну из двух вещей:
измените свой запрос, чтобы проверить значение nullity:
where...( req.status is null OR req.status in (2,5) )...
переместите тест против req.status
в критерии соединения:
left join requests req on req.app_id = apps.id and req.uid = {$user_id} and req.status in (2,5)
SELECT DISTINCT apps.*, req.status FROM applications AS apps LEFT JOIN requests AS req on req.app_id = apps.id WHERE apps.id = {$app_id}
LEFT JOIN
отобразит все ваши приложения, даже если соответствующие запросы отсутствуют.
SELECT DISTINCT apps.id, apps.*, req.status FROM applications apps LEFT JOIN requests req ON req.? = applications.? WHERE apps.id = {$app_id}
Вам нужно добавить столбец ( ?
), Который связывает обе таблицы вместе.
Вам нужно будет использовать явный LEFT JOIN следующим образом:
SELECT DISTINCT apps.id, apps.*, req.status FROM applications AS apps LEFT JOIN requests AS req ON apps.whatever_field_relates = req.whatever_field_relates WHERE apps.id = {$app_id}
Использование неявных JOINS, таких как FROM table1, table2
не является хорошей практикой IMO. Это затрудняет для других программистов понимание точной природы JOIN с первого взгляда без необходимости ссылаться на схему базы данных.
SELECT DISTINCT app.*,req.status from applications apps left join request as req on req.appid = apps.id where apps.id ={$app_id}
Выполнение левого соединения сделает трюк, я привык к синтаксису TSQL, но я уверен, что он будет работать в Mysql. Вам нужно указать идентификатор ваших приложений в обеих таблицах, чтобы иметь возможность присоединиться к ним.
В вашем запросе используется неявное перекрестное соединение, выбор данных из двух таблиц без указания способа связывания двух таблиц. То, что вы действительно хотите, – это левое соединение.
SELECT DISTINCT apps.id, apps.*, req.status FROM applications AS apps LEFT JOIN requests AS req ON apps.id = req.apps_id /* Guessing on the relationship here */ WHERE apps.id = {$app_id}
После правильного синтаксиса посмотрите, действительно ли DISTINCT
необходим для этого запроса. Это может быть дорогостоящим издержками, которые могут быть устранены.
EDIT : следующий раздел добавляется в ответ на отредактированный вопрос.
Когда вы проверяете столбец LEFT JOINed ( req.status
в вашем случае) в предложении WHERE, вы вынуждаете это соединение вести себя так, как если бы это был INNER JOIN. Вместо этого сделайте эти тесты частью условий соединения.
SELECT DISTINCT apps.*, req.status FROM applications AS apps LEFT JOIN requests AS req ON (req.app_id = apps.id AND req.uid = {$user_id}) AND (req.status = 2 OR req.status = 5) WHERE apps.id = {$app_id}