Как удалить строки в таблице MySQL, указанной данными из одной таблицы (в одном выражении)?
Я хочу удалить строки из таблицы "Книга", где раньше было два столбца.
Я успешно выбрал идентификаторы строк, которые должны быть удалены следующим образом:
SELECT all_dupes.book_id
FROM (SELECT *
FROM Book as BBook NATURAL JOIN Book as BBBook
WHERE book_id NOT IN (SELECT book_id
FROM Book as BBook NATURAL JOIN Book as BBBook
GROUP BY buying_price,
selling_price
HAVING Count(*) = 1
ORDER BY book_id)
ORDER BY book_id) AS all_dupes
WHERE book_id NOT IN (SELECT book_id
FROM Book as BBook NATURAL JOIN Book as BBBook
GROUP BY buying_price,
selling_price
HAVING Count(*) >= 2
ORDER BY book_id);
... но когда я пытаюсь удалить строки с
DELETE FROM Book
WHERE book_id IN (
<expression as above without tailing ;>
) ;
Я получаю ошибку ERROR 1093 (HY000): Table 'Book' is specified twice, both as a target for 'DELETE' and as a separate source for data
Я уже пытался создать псевдоним таблицы и естественным образом присоединить ее к себе, как предлагалось в других вопросах, касающихся этой проблемы.
Также я прочитал довольно много вопросов здесь, но они в основном очень специфичны, и я не понимаю, как изменить мой запрос на удаление с помощью ответов, предоставленных там.
Что я должен изменить, чтобы сделать это? Разделение выражения не вариант (то есть не должно быть двух ;
, но только одно выражение).
Используемая база данных: MariaDB
1 ответ
Есть несколько проблем с вашим SQL. Сначала я бы это исправил, хотя ваша СУБД не отклоняет запрос. Это может решить проблему, потому что в вашем операторе DELETE вы, возможно, наконец-то выдвинули систему за пределы своего предела В любом случае это прояснит вопрос.
ORDER BY
в стандартном SQL допускается только один раз, во внешнем предложении SELECT. Это способ возврата строк вызывающему процессу в определенном порядке, а не способ внутреннего выражения порядка в процессоре SQL. Ваш дополнительныйORDER BY
s не влияют на ваш запрос, поэтому удалите их.GROUP BY
должен повторять любые имена столбцов, не агрегированные в предложении SELECT. Потому что вы выбираетеbook_id
Вы также должны сгруппировать поbook_id
,
Я сомневаюсь, что вам действительно нужны все эти соединения в любом случае. Я не уверен, что вы пытаетесь сделать, но я думаю, что ваш запрос может быть просто
delete Book
where exists ( select 1
from Book as B
where B.book_id = Book.book_id
group by B.book_id, B.buying_price, B.selling_price
having count(*) > 1
)
Это исключило бы все строки с book_id, для которого любая комбинация {book_id, purchase_price, selling_price} не является уникальной. Но я не уверен, что ты действительно этого хочешь.
Я хочу удалить строки из таблицы "Книга", где раньше было два столбца.
Да, в SQL нет "до", потому что нет порядка. Я думаю, что вы имеете в виду, что если у вас есть 3 "дублирующих" строки, вы хотели бы удалить лишние 2. SQL не имеет такой операции.
SQL работает по логике предикатов: строки удаляются в зависимости от того, соответствуют ли они некоторым критериям. Дублирующие строки по определению все соответствуют одинаковым критериям. Поскольку нет порядка, нет понятия об удалении всех подходящих, кроме первого.
Надо сказать, что лучшим решением является предотвращение дублирования, прежде всего, путем правильного объявления уникальности в определении таблицы. В противном случае, средство обычно состоит в том, чтобы вставить отдельный набор во временную таблицу, удалить в основной таблице все те, которые существуют во временной таблице, вставить из временной в основную и удалить временную таблицу.