Рассмотрим две таблицы:
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.