MySQL DELETE FROM с подзапросом UNION по условию IN

Я споткнулся на любопытной ошибке SQL. Последний запрос не работает. Конечно, я могу просто разделить это DELETE на три запроса, но мне действительно интересно, почему MySQL не позволяет мне сделать это таким образом.

Небольшой пример:

(SELECT id FROM stairs WHERE building = 123)
UNION
(SELECT id FROM lift WHERE building = 123)
UNION
(SELECT id FROM qrcodeid WHERE building = 123)

работает!

DELETE FROM startpoint WHERE id IN (SELECT id FROM stairs WHERE building = 123)

тоже работает!

Тогда как

DELETE FROM startpoint WHERE id IN (
    (SELECT id FROM stairs WHERE building = 123)
    UNION
    (SELECT id FROM lift WHERE building = 123)
    UNION
    (SELECT id FROM qrcodeid WHERE building = 123)
)

вызывает ошибку

#1064 - У вас ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с «UNION (SELECT id FROM lift WHERE building = 123) UNION (SELECT id FROM qrc» в строке 3

Кто-нибудь знает?


person Julian Habekost    schedule 20.06.2013    source источник


Ответы (2)


Вместо этого попробуйте эту версию:

DELETE FROM startpoint
    WHERE id IN (select *
                 from ((SELECT id FROM stairs WHERE building = 123)
                       UNION
                      (SELECT id FROM lift WHERE building = 123)
                       UNION
                      (SELECT id FROM qrcodeid WHERE building = 123)
                )

Я думаю, что проблема заключается в загадочной проблеме с определением подзапроса. Подзапрос — это оператор select, тогда как union — это конъюнкция операторов select.

РЕДАКТИРОВАТЬ:

На самом деле, если вам нужна эффективность, вы бы вообще не использовали этот подход. Я просто пытался показать, как исправить ошибку. Лучшим решением будет:

DELETE sp FROM startpoint sp
    WHERE EXISTS (select 1 from stairs s where s.building = 123 and s.id = sp.id) or
          EXISTS (select 1 from lift l where l.building = 123 and l.id = sp.id) or
          EXISTS (select 1 from qrcodeid q where q.building = 123 and q.id = sp.id);

Индексы рекомендуются на stairs(id, building), lift(id, building) и qrcodeid(id, building).

person Gordon Linoff    schedule 20.06.2013
comment
Это работает (как только ошибки SQL исправлены - см. Мое редактирование). Это не так эффективно, как решение rkpasia, но оно работает в случаях, когда требуются круглые скобки для членов объединения, например, если LIMIT используется в дочерних запросах. - person Nathan Stretch; 19.06.2014

Попробуйте этот SQL

DELETE FROM startpoint WHERE id IN (
SELECT id FROM stairs WHERE building = 123
UNION
SELECT id FROM lift WHERE building = 123
UNION
SELECT id FROM qrcodeid WHERE building = 123)
person rpasianotto    schedule 20.06.2013
comment
Как видите, скобок нет! - person rpasianotto; 22.06.2013