ЛЕВОЕ СОЕДИНЕНИЕ, где не возвращаются результаты

#mysql #sql

#mysql #sql

Вопрос:

Есть две таблицы со столбцами, и я делаю базовое соединение по ЛЕВОМУ КРАЮ:

Случай 1

 SELECT g_users.id, g_users.username, f_list.user_id
FROM g_users

LEFT JOIN f_list 
    ON f_list.friend_id = g_users.id 

WHERE g_users.username IN ('meme', 'john', 'doe')
    AND g_users.id != 4
 

Результат:
введите описание изображения здесь

Все хорошо!

Случай 2, применяемый к тем же записям

 SELECT g_users.id, g_users.username, f_list.user_id
FROM g_users

LEFT JOIN f_list ON 
    f_list.friend_id = g_users.id 

WHERE g_users.username IN ('meme', 'john', 'doe')
    AND g_users.id != 4
    AND f_list.user_id != 4
 

Результат:
введите описание изображения здесь

Я ожидал вернуть записи doe, но он ничего не вернул. Чего мне не хватает?

Комментарии:

1. Ваше использование GROUP BY недопустимо. В SELECT списке есть столбцы, которые несовместимы со столбцами GROUP BY — из f_list таблицы.

2. Не используйте GROUP BY with SELECT * . Такой запрос не имеет смысла и не выполняется нигде, кроме MySQL (может быть разрешен в SQLite). Извиняюсь, вам пришлось изучать SQL таким образом!

3. Спасибо за ответ. Я удалил group by. Это все еще не работает. Я обновил вопрос.

4. Если вы НИКОГДА не используете SELECT * , вы, вероятно, не ошибетесь.

5. A LEFT JOIN WHERE (с условиями, использующими таблицу с левым соединением) = INNER JOIN . Некоторое время назад WHERE использовался для неявного соединения!

Ответ №1:

Ах, удивительный мир обработки нулевых значений.

Проблема возникает при выполнении сравнения в вашем предложении WHERE с таблицей, к которой вы присоединяетесь слева. У вас есть этот f_list.user_id != 4 . Для строк, которые не совпадают с вашим соединением по левому краю, это выражение вычисляется, если null != 4, что равно false, потому что это нулевое значение.

У вас есть 2 уникальных совпадающих значения, null и 4, из которых оба исключаются в приведенном выше заявлении, что оставляет вас с 0 строками в результате.

Чтобы получить желаемый результат, вы можете обернуть f_list.user_id в функцию обработки null, такую как COALESCE .

Комментарии:

1. COALESCE не будет работать в этом сценарии, поскольку он все равно вернет значение null для этого условия

2. Подразумевается, что вам нужно будет предоставить как минимум 2 аргумента, такие как COALESCE(user_id, -1) .

Ответ №2:

Если у вас есть ANSI_NULLS ДЛЯ условия сравнения, содержащего нулевое значение, возвращает unknown, а не true или false. Ваше условие и f_list.user_id != 4 не возвращают true для строки doe

Вы можете попробовать запустить

 SET ANSI_NULLS OFF
 

перед тем, как ваш запрос или escape ОБНУЛЯТСЯ

ANSI_NULLS

РЕДАКТИРОВАТЬ Как объяснил пользователь, это Mariadb, единственный доступный вариант — экранирование нулей с помощью AND (f_list.user_id != 4 или И f_list.user_id РАВНО НУЛЮ)

Комментарии:

1. Я использую MariaDB, а не MSSQL. Я не могу его отключить

2. Прошу прощения, я не заметил СУБД, которую вы используете. Вам нужно будет выполнить безопасное сравнение с нулем или вручную добавить «или f_list.user_id равно нулю».

3. Мое удовольствие! 🙂