Left join - Поведение при использовании where (null <> 'p') - PullRequest
0 голосов
/ 24 мая 2019

В этом выборе представлены 4 записи, представляющие собой три нуля за отсутствие корреляции и только одну с корреляцией.

enter image description here

Результат:

enter image description here

Когда я добавляю ограничение в WHERE pc.contype <> 'p', все записи только, а не только 'p'.

enter image description here

Результат:

enter image description here

Я не могу понять, что происходит, это какое-то правило, которое я отпускаю?

Ответы [ 5 ]

1 голос
/ 24 мая 2019

То, что вы ищете, является NULL -безопасным сравнением.Postgres поддерживает стандартную функцию ANSI / ISO для этого, поэтому я бы порекомендовал:

WHERE contype IS DISTINCT FROM 'p'

Это объясняется в документации .

1 голос
/ 24 мая 2019

NULL не равно (или не равно) ничему, включая сам NULL.Игнорируя, что вы используете LEFT JOIN, и предполагая, что contype обнуляемо: условие WHERE contype <> 'p' не будет соответствовать NULL просто потому, что NULL <> 'p' неизвестно, не верно!

Вы должны написать следующее, чтобы получитьстроки, в которых нет совпадений в правой таблице:

WHERE contype <> 'p' OR contype IS NULL
1 голос
/ 24 мая 2019

Так что здесь происходит то, что pg_indexes имеет 4 строки, соответствующие вашим условиям WHERE.Когда вы оставляете соединение, вы сохраняете все строки, даже если нет соединения.В вашем случае к pg_constraint присоединяется только одна строка.

Когда LEFT JOIN не удается соединить строку, он заполняет все потенциальные столбцы значением NULL.Это означает, что в вашем случае 3 строки, которые не присоединились к pg_constraint, теперь имеют NULL для всех столбцов, указанных в pg_constraint.

Наконец, когда вы сравниваете ____ <> 'p', вы пропускаетеправило того, как SQL обрабатывает значения NULL.NULL рассматривается как отсутствие значения, а не как что-то, с чем вы можете сравнить.Любая попытка использовать скалярное сравнение потерпит неудачу.

Вы можете исправить это, изменив значение на WHERE (pc.contype IS NULL OR pc.contype <> 'p')

0 голосов
/ 24 мая 2019

Дополнительное условие pc.contype <> 'p' в предложении WHERE эффективно побеждает внешнее соединение и преобразует его во внутреннее соединение. Вместо этого поместите этот предикат в предложение ON.

Вы, вероятно, хотите что-то вроде:

select
  pc.contype
from pg_indexes pi
left join pg_constraint pc on pi.indexname = pc.conname
                          and pc.contype <> 'p'
where pi.tablename = 'mytable'
0 голосов
/ 24 мая 2019

Вы используете левое соединение , поэтому данные pg_indexes всегда будут возвращаться, даже если pg_constraints не имеет соответствующих данных для того же ключа.Это то, что происходит в первом запросе.Во втором запросе вы добавили проверку только для того, чтобы возвращать данные, в которых значение pg_constraints не равно p, на этот раз значения NULL также будут проверены и не будут отображаться при сбое проверки.Если бы эта проверка была вместо этого в предложении соединения, она все равно показала бы значения NULL, но она находится в предложении where и отфильтровывает весь набор результатов.Левое объединение - это внешнее объединение, которое всегда возвращает все данные из таблицы слева от объединения, даже если для одинаковых значений справа от объединения ничего не существует, вам следует помнить об этом.

...