Обновление: этот ответ охватывает общую классификацию ошибок. Более подробный ответ о том, как лучше всего обрабатывать точный запрос OP, см. В других ответах на этот вопрос
. В MySQL вы не можете изменить ту же таблицу, которую используете в SELECT часть. Это поведение задокументировано по адресу: http://dev.mysql.com/doc/refman/5.6/en/update.html
Возможно, вы можете просто присоединиться к таблице самим себе
Если логика достаточно простая, чтобы переформатировать запрос, потеряйте подзапрос и присоединитесь к таблице, используя соответствующие критерии выбора. Это заставит MySQL видеть таблицу как две разные вещи, позволяя деструктивным изменениям идти вперед.
UPDATE tbl AS a
INNER JOIN tbl AS b ON ....
SET a.col = b.col
Альтернативно, попробуйте вложить подзапрос глубже в предложение from ...
Если вам абсолютно необходим подзапрос, есть обходной путь, но он уродлив по нескольким причинам, включая производительность:
UPDATE tbl SET col = (
SELECT ... FROM (SELECT.... FROM) AS x);
Вложенный подзапрос в предложении FROM создает неявную временную таблицу , поэтому он не считается той же таблицей, которую вы обновляете.
... но следите за оптимизатором запросов
Однако будьте осторожны, что из MySQL 5.7.6 и далее оптимизатор может оптимизировать подзапрос , и все еще дают вам ошибку. К счастью, переменную optimizer_switch
можно использовать для отключения этого поведения; хотя я не мог рекомендовать делать это как нечто большее, чем краткосрочное исправление, или для небольших одноразовых задач.
SET optimizer_switch = 'derived_merge=off';
Благодаря Peter V. Mørch для этого совета в комментариях.
Примерный метод был от барона Шварца, , первоначально опубликованного в Nabble , перефразированного и расширенного здесь.
Из того, что я могу извлечь из вашего вопроса, похоже, что вы находитесь на правильном пути с вашим запросом left join
, однако, поскольку ваш запрос qAllDatesAllEmp
содержит основные данные, вы должны вывести данные из этого запроса для записи, для которых соответствующие значения равны нулю в вашем запросе qDailyWorkEmp
.
В вашем запросе также есть опечатка в этой строке:
qAllDatesAllEmp.WhatDate = qDailyWorkEmp.DailyDate
Как вы указали в своем вопросе, запрос qAllDatesAllEmp
содержит поля:
WhatDate
не является одним из этих полей.
Вам также нужно будет присоединиться к полю empID
в обоих запросах, чтобы сравнивать поле даты на основе на сотрудника , а не сравнивать каждую дату с даты всех сотрудников - следовательно, ваши критерии объединения должны быть:
qAllDatesAllEmp LEFT JOIN qDailyWorkEmp ON
qAllDatesAllEmp.WorkDate = qDailyWorkEmp.DailyDate AND
qAllDatesAllEmp.empID = qDailyWorkEmp.empID
С учетом предоставленной информации я мог бы предложить следующее:
SELECT
qAllDatesAllEmp.empID,
qAllDatesAllEmp.empName,
qAllDatesAllEmp.CityBased
qAllDatesAllEmp.WorkDate as MissingDate
FROM
qAllDatesAllEmp LEFT JOIN qDailyWorkEmp ON
qAllDatesAllEmp.WorkDate = qDailyWorkEmp.DailyDate AND
qAllDatesAllEmp.empID = qDailyWorkEmp.empID
WHERE
qDailyWorkEmp.DailyDate IS NULL