Почему поведение MySQL «ИСТИНА», «НЕ ИСТИНА», «ЛОЖЬ», «НЕ ЛОЖЬ» отличается в зависимости от того, где и где - PullRequest
0 голосов
/ 22 января 2019

Рассмотрим две таблицы:

table1

id
1
2
3

table2

id, deleted
2, 0
3, 1

Предположим, я хочу получить все строки из таблицы1, которые не помечены как "удаленные" в таблице2, то есть строки 1 и 2. Рассмотрим следующий SQL (в MySQL):

SELECT id
FROM table1
LEFT JOIN table2 USING (id)
WHERE deleted <> 1

Этот SQL, очевидно, возвращает просто строку с id = 2.

Я могу сделать извращение вот так:

SELECT id
FROM table1
LEFT JOIN table2 USING (id)
WHERE COALESCE(deleted, 0) = 0

А потом я получу строки 1 и 2.

Но я хотел более элегантный способ. MySQL имеет эти приятные проверки для логических значений, ИСТИНА, НЕ ИСТИНА, ЛОЖЬ, НЕ ЛОЖЬ, которые принимают значения NULL. Итак, учтите это:

SELECT id, deleted, deleted IS NOT TRUE
FROM table1
LEFT JOIN table2 USING (id)

Результат:

id, deleted, deleted IS NOT TRUE
1, NULL, TRUE
2, 0, TRUE
3, 1, FALSE

Отлично выглядит, да? теперь, если я просто вставлю это в предложение WHERE:

SELECT id
FROM table1
LEFT JOIN table2 USING (id)
WHERE deleted IS NOT TRUE

О нет! Я снова получаю только строку 2!

Однако, если я добавлю условие в предложение HAVING, оно начнет работать:

SELECT id
FROM table1
LEFT JOIN table2 USING (id)
HAVING deleted IS NOT TRUE

Я получаю строки 1 и 2.

Полностью сбивает с толку. Похоже, ошибка в MySQL.

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Как я и подозревал @BillKarwin, это старая ошибка 2012 года в MySQL: (

"WHERE var TRUE TRUE дает слишком мало" (https://bugs.mysql.com/bug.php?id=67732)

0 голосов
/ 22 января 2019

Я думаю, вы просто хотите NOT EXISTS:

SELECT t1.id
FROM table1 t1 
WHERE NOT EXISTS (SELECT 1
                  FROM table2 t2
                  WHERE t1.id = t2.id AND t2.is_deleted = 1
                 );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...