У меня есть правое внешнее соединение, которое делает почти то, что я хочу ...
SELECT
users_usr.firstname_usr,
users_usr.lastname_usr,
credit_acc.given_credit_acc,
users_usr.created_usr,
users_usr.sitenum_usr,
users_usr.original_aff_usr,
users_usr.id_usr
FROM
credit_acc
right Outer Join users_usr ON credit_acc.uid_usr = users_usr.id_usr
Проблема в том, что я хочу добавить
where credit_acc.type_acc = 'init'
Но это избавляет от всех пользователей, у которых нет строки в credit_acc ... что ПОЧЕМУ мне нужно правильное внешнее соединение.
Есть ли способ получить это без необходимости выполнять два запроса и объединение?
Я думаю, что вам нужно уточнить, что вы ищете, чтобы вернуть. Вы хотите, чтобы все пользователи имели "init" ИЛИ вообще не имели кредитной учетной записи? Здесь могут помочь примеры данных и ожидаемые результаты, если вы сможете охватить все возможные сценарии.


SELECT
users_usr.firstname_usr,
users_usr.lastname_usr,
credit_acc.given_credit_acc,
users_usr.created_usr,
users_usr.sitenum_usr,
users_usr.original_aff_usr,
users_usr.id_usr
FROM
credit_acc
right Outer Join users_usr ON credit_acc.uid_usr = users_usr.id_usr
WHERE credit_acc.type_acc = 'init' OR credit_acc.type_acc is NULL
Или, как указал @Tomalak:
WHERE COALESCE(credit_acc.type_acc, 'init') = 'init'
который май будет быстрее (см. комментарии).
В качестве альтернативы: ГДЕ COALESCE (credit_acc.type_acc, 'init') = 'init'
Хороший вызов - вторая оптимизация COALESCE здесь.
@Tomalak, я не очень хорошо знаком с COALESCE, но я нашел его и добавил к ответу, спасибо, что научил меня чему-то новому.
Фактически, добавление Coalesce к предложению where предотвратит возможность саргетирования запроса, поэтому любые индексы, которые могут существовать в столбце type_acc, использоваться не будут. Во всяком случае, использование coalesce замедлит запрос.
Вы пробовали следующее?
SELECT
users_usr.firstname_usr,
users_usr.lastname_usr,
credit_acc.given_credit_acc,
users_usr.created_usr,
users_usr.sitenum_usr,
users_usr.original_aff_usr,
users_usr.id_usr
FROM
credit_acc
right Outer Join users_usr ON credit_acc.uid_usr = users_usr.id_usr and credit_acc.type_acc = 'init'
"И" здесь не работает синтаксически. Вы еще не начали предложение предиката. Должно быть «где». Я предполагаю, что OP пробовал именно это, но, как он говорит, он отфильтровывает желаемые строки, где type_acc равен NULL.
Если строка не существует, credit_acc.type_acc должно быть нулевым. Вы можете попробовать что-то вроде этого:
WHERE credit_acc.type_acc = 'init' OR credit_acc.type_acc IS NULL;
Это будет работать, только если в credit_acc.type_acc нет нулевых полей.
Вы хотите, чтобы все записи из двух таблиц были объединены по идентификатору пользователя, ГДЕ credit_acc равно 'init' ИЛИ там, где нет строки credit_acc, которую нужно объединить? Как насчет
where credit_acc.type_acc is null OR credit_acc.type_acc = 'init'
Я бы сделал предикат:
WHERE credit_acc.uid_usr IS NULL OR credit_acc.type_acc = 'init'
Это даст вам строки, в которых нет совпадений по UID_USR, и строки, в которых есть совпадения, и тип учетной записи - init.
Другое предложенное решение (проверка type_acc на NULL) также даст вам строки, в которых есть совпадение по UID_USR, а фактическое значение для типа учетной записи - NULL.
Если значение credit_acc.type_acc не может быть равно NULL, разницы между ними нет. Если это возможно, вам нужно решить, хотите ли вы включить эти строки в свой набор результатов.
Просто добавьте еще один предикат в условие соединения.
SELECT U.firstname_usr, U.lastname_usr, C.given_credit_acc,
U.created_usr, U.sitenum_usr, U.original_aff_usr, U.id_usr
From credit_acc C Right Join users_usr U
On C.uid_usr = U.id_usr
And C.type_acc = 'init'
Это работает, потому что условия соединения применяются ДО того, как несовпадающие записи с «другой» стороны «внешнего» соединения добавляются в набор результатов, тогда как условия Where применяются после объединения двух таблиц ...
Этот синтаксис также более четко отображает ваши намерения ...
Просто примечание к соглашению: я редко (если вообще) вижу ПРАВЫЕ соединения - обычно это ЛЕВЫЕ соединения. Итак, в этом случае я бы начал с users_usr, а затем оставил соединение с credit_acc. Я тоже думаю, что это лучше читается.