SQL: невозможно использовать предложение UPDATE после использования UNION или подзапроса, пока аналогичный SELECT все еще работает - PullRequest
0 голосов
/ 28 февраля 2019

Итак, у меня есть база данных со следующей структурой:

  • wp_giantbomb_game_list ( post_id , важно)

  • wp_game_attribute_company ( ID , важно)

  • wp_game_relation_publisher ( ID , game_id , attribute_id )

  • wp_game_relation_developer ( ID , game_id , attribute_id )

Важным тегом является логическое значение, которое говорит, важна ли игра.В настоящее время я делаю компании важными вручную.Теперь я хочу создать запрос, который устанавливает все игры как важные, для которых либо разработчик, либо издатель считают важным.Отношения между издателем и разработчиком определяются через таблицы "game_relation", где game_id ссылается на "wp_giantbomb_game_list" и "attribute_id".

Таким образом, моей первой целью было попытаться иобъединить данные из обеих таблиц отношений в одну.Для меня не имело значения, был ли издатель или разработчик определен как "важный" в конце концов.

Я использовал следующий запрос, чтобы вернуть все теги "game_id", у которых есть важный издатель или разработчик.

SELECT PUB.game_id FROM wp_game_relation_publisher PUB INNER JOIN 
wp_game_attribute_company COM ON PUB.attribute_id = COM.ID WHERE COM.important = 1 
UNION SELECT DEV.game_id FROM wp_game_relation_developer DEV INNER JOIN
wp_game_attribute_company COM ON DEV.attribute_id = COM.ID WHERE COM.important = 1 
ORDER BY game_id ASC;

Этот запрос был очень быстрым и выполнил свою задачу.Теперь я просто хотел использовать game_id с предложением WHERE IN ala

SELECT * FROM `wp_giantbomb_game_list` GAMELIST WHERE GAMELIST.post_id IN (
    SELECT PUB.game_id FROM wp_game_relation_publisher PUB INNER JOIN 
    wp_game_attribute_company COM ON PUB.attribute_id = COM.ID WHERE COM.important = 1 
    UNION SELECT DEV.game_id FROM wp_game_relation_developer DEV INNER JOIN
    wp_game_attribute_company COM ON DEV.attribute_id = COM.ID WHERE COM.important = 1 
    ORDER BY game_id ASC);

Этот запрос не работал вообще.PHPMyAdmin просто не отвечал, заставляя меня перезагрузить сайт.Затем я попробовал обходной путь без UNION, просто добавив OR в предложение WHERE IN.

SELECT * FROM `wp_giantbomb_game_list` GAMELIST WHERE GAMELIST.post_id IN(
    SELECT PUB.game_id FROM wp_game_relation_publisher PUB INNER JOIN
    wp_game_attribute_company COM ON PUB.attribute_id = COM.ID WHERE COM.important = 1)
    or GAMELIST.post_id IN (SELECT DEV.game_id FROM wp_game_relation_developer DEV INNER JOIN
    wp_game_attribute_company COM ON DEV.attribute_id = COM.ID WHERE COM.important = 1 );

Это сработало, но затем использование сопоставимого оператора обновления заставило PHPMyAdmin просто не реагироватьбольше.

UPDATE `wp_giantbomb_game_list` GAMELIST SET important = 1 WHERE GAMELIST.post_id IN(
    SELECT PUB.game_id FROM wp_game_relation_publisher PUB INNER JOIN
    wp_game_attribute_company COM ON PUB.attribute_id = COM.ID WHERE COM.important = 1)
    or GAMELIST.post_id IN (SELECT DEV.game_id FROM wp_game_relation_developer DEV INNER JOIN
    wp_game_attribute_company COM ON DEV.attribute_id = COM.ID WHERE COM.important = 1 );

Так что теперь я просто понятия не имею, что происходит.Мой вопрос, таким образом, кто-нибудь знает, что происходит, и кто-нибудь знает, как решить эту проблему?

Огромное спасибо всем, кто пришел сюда заранее!

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Правильно, я пытался использовать ваш код, и у него была та же проблема.Но это заставило меня немного покопаться, и я увидел, что у меня нет никаких индексов для внешних ключей.Добавил пару индексов BTREE к внешним ключам, и теперь мой и код, приведенный в ответах, работают отлично.

Большое спасибо за помощь и извините за неудобства!

0 голосов
/ 28 февраля 2019

Попробуйте использовать EXISTS:

UPDATE `wp_giantbomb_game_list` gl
    SET important = 1
    WHERE EXISTS (SELECT 1
                  FROM wp_game_relation_publisher p INNER JOIN
                       wp_game_attribute_company c
                       ON p.attribute_id = c.ID
                  WHERE c.important = 1 AND gl.post_id = p.game_id
                 ) OR
          EXISTS (SELECT 1
                  FROM wp_game_relation_developer d INNER JOIN
                       wp_game_attribute_company c
                       ON d.attribute_id = c.ID 
                  WHERE d.important = 1 AND gl.post_id = d.game_id
                 ) ;

. Тогда вы можете воспользоваться индексами:

  • wp_game_relation_publisher(post_id, attribute_id)
  • wp_game_attribute_company(id, important)
  • wp_game_relation_developer(game_id, attribute_id)
...