Как удалить строки в таблице 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 вы, возможно, наконец-то выдвинули систему за пределы своего предела В любом случае это прояснит вопрос.

  1. ORDER BY в стандартном SQL допускается только один раз, во внешнем предложении SELECT. Это способ возврата строк вызывающему процессу в определенном порядке, а не способ внутреннего выражения порядка в процессоре SQL. Ваш дополнительный ORDER BYs не влияют на ваш запрос, поэтому удалите их.

  2. 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 работает по логике предикатов: строки удаляются в зависимости от того, соответствуют ли они некоторым критериям. Дублирующие строки по определению все соответствуют одинаковым критериям. Поскольку нет порядка, нет понятия об удалении всех подходящих, кроме первого.

Надо сказать, что лучшим решением является предотвращение дублирования, прежде всего, путем правильного объявления уникальности в определении таблицы. В противном случае, средство обычно состоит в том, чтобы вставить отдельный набор во временную таблицу, удалить в основной таблице все те, которые существуют во временной таблице, вставить из временной в основную и удалить временную таблицу.

Другие вопросы по тегам