MySQL Обновление с условием о результатах ГДЕ (РЕШЕНО) - PullRequest
0 голосов
/ 30 апреля 2020

Как обновить на основе одного / нескольких условий из результатов WHERE? Например?

UPDATE tb_a, tb_b, tb_c
SET tb_a.A = 
CASE 
  WHEN COUNT(tb_b.is_field_null IS NULL) = 0 
  THEN "OK" 
  ELSE "Nope" 
END
WHERE tb_a.a = "some" AND tb_a.b = "thing" AND tb_c.c = "else"
AND tb_a.b = tb_b.a
AND tb_c.b = tb_b.c

Приведенные таблицы:

tb_a

a          |    b        |      A
------------------------------------------
"some"     | "thing"     | "XXX"
"some"     | "thing"     | "YYY"

tb_b

a             | c           | is_field_null 
----------------------------------------------
"thing"       | "else"      | "I have things here" 
"thing"       | "else"      | NULL
"otherThing   | "otherElse" | NULL

tb_ c

b            | c           | mapper 
----------------------------------------------
"else"       | "else"      | "ZZZ" 
"else"       | "else"      | "KKK"

Я пытался без условия COUNT, в результате чего весь столбец tb_a.A был изменен на "Нет". Что похоже на

tb_a

a          |    b        |      A
------------------------------------------
"some"     | "thing"     | "Nope"
"some"     | "thing"     | "Nope"

Но с COUNT возникает ошибка Invalid use of group function. Я пробовал if, например,

SET tb_a.A = (if COUNT(tb_b.is_field_null IS NULL) = 0, "Yes", "Nope"),

условие, но все еще ошибка.

Я бы не ожидал никаких изменений вообще. Может кто-нибудь помочь?

С ответом @ forpas

Я обнаружил, что есть проблема. Если tb_b изменено на

a             | c           | is_field_null 
----------------------------------------------
"thing"       | "else"      | "I have things here" 
"thing"       | "else"      | "I have things here" 
"otherThing   | "otherElse" | NULL

, то tb_a после запроса все еще

a          |    b        |      A
------------------------------------------
"some"     | "thing"     | "Nope"
"some"     | "thing"     | "Nope"

Является ли строка CROSS JOIN (SELECT SUM(is_field_null IS NULL) counter FROM tb_b) t или WHEN NOT EXISTS(SELECT 1 FROM tb_b WHERE is_field_null IS NULL) не проверкой с возвращенными результатами из пунктов WHERE и ON? Он выполняет проверку непосредственно из необработанного tb_b?

Третий запрос из forpas работает.

Есть кое-что, что я не совсем понимаю в такой ситуации. Из первых 2 запросов forpas, если я изменю их с UPDATE на SELECT, они правильно выберут первые 2 строки в tb_b. Но в режиме UPDATE ни

CROSS JOIN (SELECT SUM(is_field_null IS NULL) counter FROM tb_b) t

, ни

WHEN NOT EXISTS(SELECT 1 FROM tb_b WHERE is_field_null IS NULL)

не выполняются с условиями WHERE и ON. Кто-нибудь может мне помочь?

ОБНОВЛЕНИЕ

Насколько мне известно, в настоящее время компактная форма вопроса на этот вопрос

UPDATE tb_a.A
CROSS JOIN (SELECT SUM(is_field_null IS NULL) counter 
   FROM tb_a
    INNER JOIN tb_b ON tb_a.b = tb_b.a
    INNER JOIN tb_c ON tb_c.b = tb_b.c
    WHERE tb_a.a = "some" AND tb_a.b = "thing" AND tb_c.c = "else"
) t
SET tb_a.A = CASE
  WHEN t.counter = 0 THEN "Yes"
  ELSE "Nope"
END
WHERE tb_a.a = "some"

Пожалуйста, обратитесь к @ Ответ forpas для полного решения формы и блестящая альтернатива на NOT EXISTS.

1 Ответ

2 голосов
/ 30 апреля 2020

Используйте правильные объединения, а также CROSS JOIN запрос, который возвращает результат COUNT(tb_b.is_field_null IS NULL), например:

UPDATE tb_a
INNER JOIN tb_b ON tb_a.b = tb_b.a
INNER JOIN tb_c ON tb_c.b = tb_b.c
CROSS JOIN (SELECT SUM(is_field_null IS NULL) counter FROM tb_b) t
SET tb_a.A = CASE 
  WHEN t.counter = 0 THEN "OK" 
  ELSE "Nope" 
END
WHERE tb_a.a = "some" AND tb_a.b = "thing" AND tb_c.c = "else"

или с NOT EXISTS:

UPDATE tb_a
INNER JOIN tb_b ON tb_a.b = tb_b.a
INNER JOIN tb_c ON tb_c.b = tb_b.c
SET tb_a.A = CASE 
  WHEN NOT EXISTS(SELECT 1 FROM tb_b WHERE is_field_null IS NULL) THEN "OK" 
  ELSE "Nope" 
END
WHERE tb_a.a = "some" AND tb_a.b = "thing" AND tb_c.c = "else"

Редактировать:

UPDATE tb_a
INNER JOIN tb_b ON tb_a.b = tb_b.a
INNER JOIN tb_c ON tb_c.b = tb_b.c
CROSS JOIN (
  SELECT SUM(is_field_null IS NULL) counter 
  FROM tb_a
  INNER JOIN tb_b ON tb_a.b = tb_b.a
  INNER JOIN tb_c ON tb_c.b = tb_b.c
  WHERE tb_a.a = "some" AND tb_a.b = "thing" AND tb_c.c = "else"
) t 
SET tb_a.A = CASE 
  WHEN t.counter = 0 THEN "OK" 
  ELSE "Nope" 
END
WHERE tb_a.a = "some" AND tb_a.b = "thing" AND tb_c.c = "else"
...