Dla "zapytania nie aktualizuje poprawnie wierszy":
Chcesz zaktualizować kolumnę b
do minimum z b
dla wszystkich wierszy mających ten sam a
Zaproponowałeś użycie następującego JOIN
aby to zrobić:
UPDATE test.tem t1
JOIN test.tem t2
ON t1.a = t2.a
SET t1.b = t2.b
WHERE t1.b > t2.b
OR t1.b IS NULL;
Wbrew temu, co myślisz, JOIN
nie wykona 1-1 JOIN
. W rzeczywistości jest to JOIN
od jak powiedziałem wczoraj
nie używasz klucza podstawowego (ani unikalnego klucza innego niż null) w klauzuli przyłączenia.
W rzeczywistości przepisując to zapytanie jako SELECT
prawdopodobnie pomoże ci zrozumieć problem:
SELECT t1.a as t1a, t1.b as t1b, t2.a as t2a,t2.b as t2b FROM tem t1 JOIN tem t2
ON t1.a = t2.a
WHERE t1.b > t2.b
OR t1.b IS NULL;
+------+---------+------+--------+
| T1A | T1B | T2A | T2B |
+------+---------+------+--------+
| 1 | (null) | 1 | 2 |
| 1 | 2 | 1 | 1 |
| 1 | (null) | 1 | 1 |
| 1 | (null) | 1 | (null) |
+------+---------+------+--------+
http://sqlfiddle.com/#!2/856a7/8
Jak zobaczysz, wiersz (1, null)
dopasuj (1, 1)
, (1, 2)
i (1, null)
. W zależności od (niedeterministycznej) kolejności wykonywania zapytania, może to przypisać dowolną z trzech możliwych wartości dla b
(nie jestem tego pewien, ale może nawet aktualizując kilka czasy). W pewnym stopniu miałeś szczęście, że podczas testowania znalazłeś „niewłaściwy” wynik!
Mam nadzieję, że to wyjaśnia nieco więcej, dlaczego zapytanie nie przynosi oczekiwanego rezultatu. Ponieważ wielostołowy UPDATE
oświadczenia nie zezwalają na ORDER BY
ani GROUP BY
klauzul, tak jak ja, aby znaleźć „dobry” wynik, nie widzę wielu innych opcji niż znalezienie minimum pierwszego poprzez podzapytanie...