Так как вы ничего не выбираете из таблицы, которую планируете LEFT JOIN
, вы можете вообще ее опустить. Использование INNER JOIN
фильтрует ваши результаты, а LEFT (OUTER) JOIN
- нет, поэтому в этом нет необходимости:
SELECT Executor_service.*, Executor.*
FROM Executor_service
INNER JOIN Executor ON Executor.user_id = Executor_service.executor_id
WHERE Executor.user_id != 236
AND Executor_service.service_id = 511
AND Executor_service.status = 'free'
AND Executor_service.mstatus = 'work'
AND Executor_service.city_id = 3538
AND Executor.balance > 0
AND Executor.status = 'free'
ORDER BY Executor.rate DESC
LIMIT 1
Посмотри, подходит ли тебе это. Если вы действительно планировали использовать LEFT JOIN
на Cancel
столе, то это путь.
Проблема с оптимизацией производительности заключается в том, что вы на самом деле вообще не используете LEFT JOIN
. Если вы действительно хотите использовать LEFT JOIN, вы не можете использовать столбец этих таблиц в предложении WHERE. Это превращает это присоединение к INNER JOIN.
Еще одна небольшая вещь: глядя на ваш код, лучше связать ваши таблицы Cancel
и Executor_service
через общий столбец city_id
, чем писать city_id =3538
дважды:
Код с этими исправлениями выглядит следующим образом (с сохранением таблицы Cancel
в INNER JOIN
, как это было на самом деле раньше):
SELECT Executor_service.*, Executor.*
FROM Executor_service
INNER JOIN Executor ON Executor.user_id = Executor_service.executor_id
INNER JOIN Cancel ON Cancel.executor_id = Executor.user_id AND Cancel.city_id = Executor_service.city_id
WHERE Cancel.order_id IS NULL
AND Executor.user_id != 236
AND Executor_service.service_id = 511
AND Executor_service.status = 'free'
AND Executor_service.mstatus = 'work'
AND Executor_service.city_id = 3538
AND Executor.balance > 0
AND Executor.status = 'free'
ORDER BY Executor.rate DESC
LIMIT 1
Кроме того, если вы хотите, чтобы пользователь LEFT JOIN
отфильтровал результаты, чтобы исключить записи в таблице Cancel
(как указано в комментариях), тогда вы можете использовать следующий код:
SELECT Executor_service.*, Executor.*
FROM Executor_service
INNER JOIN Executor ON Executor.user_id = Executor_service.executor_id
WHERE Executor.user_id != 236
AND Executor_service.service_id = 511
AND Executor_service.status = 'free'
AND Executor_service.mstatus = 'work'
AND Executor_service.city_id = 3538
AND Executor.balance > 0
AND Executor.status = 'free'
AND NOT EXISTS (SELECT Cancel.order_id
FROM Cancel
WHERE Cancel.executor_id = Executor.user_id AND Cancel.city_id = Executor_service.city_id)
ORDER BY Executor.rate DESC
LIMIT 1
В качестве альтернативы вы могли бы написать свой запрос, используя LEFT JOIN
(с добавлением Cancel.order_id
среди выбранных значений), а затем переместить условие WHERE Cancel.order_id IS NULL
во внешний запрос.
TL; DR:
Если вы действительно хотите использовать INNER JOIN для таблицы Cancel
, вы можете вообще ее опустить. Если вы хотите использовать его для исключения данных, связанных с существующими данными в таблице Cancel
, вам следует переписать их, как указано в последнем коде (или с помощью подзапроса). Если ничего из этого - трудно оптимизировать код, не зная данных, стоящих за ним ... В этом случае, по крайней мере, я надеюсь, что эти небольшие данные помогли вам лучше понять, что вы действительно хотите и что вы получаете.