Вопрос о присоединении к запросу

У меня есть правое внешнее соединение, которое делает почти то, что я хочу ...

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 ... что ПОЧЕМУ мне нужно правильное внешнее соединение.

Есть ли способ получить это без необходимости выполнять два запроса и объединение?

Просто примечание к соглашению: я редко (если вообще) вижу ПРАВЫЕ соединения - обычно это ЛЕВЫЕ соединения. Итак, в этом случае я бы начал с users_usr, а затем оставил соединение с credit_acc. Я тоже думаю, что это лучше читается.

Michael Haren 13.11.2008 20:43

Я думаю, что вам нужно уточнить, что вы ищете, чтобы вернуть. Вы хотите, чтобы все пользователи имели "init" ИЛИ вообще не имели кредитной учетной записи? Здесь могут помочь примеры данных и ожидаемые результаты, если вы сможете охватить все возможные сценарии.

Tom H 13.11.2008 20:59
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
2
172
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий
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'

Tomalak 13.11.2008 20:45

Хороший вызов - вторая оптимизация COALESCE здесь.

Skeolan 13.11.2008 20:46

@Tomalak, я не очень хорошо знаком с COALESCE, но я нашел его и добавил к ответу, спасибо, что научил меня чему-то новому.

Robert Gamble 13.11.2008 20:55

Фактически, добавление Coalesce к предложению where предотвратит возможность саргетирования запроса, поэтому любые индексы, которые могут существовать в столбце type_acc, использоваться не будут. Во всяком случае, использование coalesce замедлит запрос.

George Mastros 13.11.2008 21:00

Вы пробовали следующее?

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.

Dave Costa 13.11.2008 21:50

Если строка не существует, 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 применяются после объединения двух таблиц ...

Этот синтаксис также более четко отображает ваши намерения ...

Другие вопросы по теме