«Несколько» поисков с Postgres - PullRequest
0 голосов
/ 21 мая 2018

Обычно я пытаюсь получить значение из одной таблицы, а затем искать это значение в 3 других таблицах.Но я хочу сделать все это одним запросом.

select user_id from users where email = 'bob@example.com

Значение этого поиска должно быть включено в запрос, например:

SELECT *
FROM table1
JOIN table2 ON (table1.user_id = 
table2.user_id)
WHERE table1.user_id  =  <<<THE RESULTS FROM THE FIRST QUERY>>>
OR table2.user_id = <<<THE RESULTS FROM THE FIRST QUERY>>>

Еслиuser_id не находится в первой таблице, этот JOIN все еще будет работать?

1 Ответ

0 голосов
/ 21 мая 2018

A CTE - Общее табличное выражение (которое AFAIK всегда материализуется в Postgres) будет служить в качестве заполнителя для вашего первого запроса, который вы затем сможете использовать для объединения в другие таблицы.Кроме того, UNION звучит как то, что вы хотите, как стиль OR для нахождения соответствующих данных в одной или нескольких таблицах t1 .. t3, например:

WITH cteUsers AS
(
    select user_id from users where email = 'bob@example.com'
)
SELECT t1.user_id, t1.othercol, ...
FROM table1 t1 INNER JOIN cteUsers cte on t1.user_id = cte.user_id
UNION
SELECT t2.user_id, t2.othercol, ...
FROM table1 t2 INNER JOIN cteUsers cte on t2.user_id = cte.user_id
UNION
SELECT t3.user_id, t3.othercol, ...
FROM table1 t3 INNER JOIN cteUsers cte on t3.user_id = cte.user_id;

Спримечания:

  • Число и типы, возвращаемые в столбцах othercol в различных таблицах t1..t3, должны совпадать.
  • Если один и тот же пользователь сопоставляется в нескольких таблицах сте же самые значения othercol, тогда UNION будет иметь эффект удаления дубликатов (аналогично DISTINCT).Замените это на UNION ALL, если вы хотите дублировать строки.
  • Если более чем одна таблица t1 .. t3 удастся сопоставить объединение с users, то будет возвращаться одна строка на каждую совпавшую таблицу (если это неудалено отличным, как указано выше)
  • Если в одной из таблиц 1, 2 или 3 нет совпадений, запрос вообще ничего не даст.Если вы хотите, чтобы одна строка возвращалась из users независимо от совпадения (with nulls for unmatched columns), тогда требуется LEFT JOIN между пользователями и хотя бы одной из таблиц t1..t3

Редактировать - Re: Обеспечение того, чтобы строка users всегда возвращала хотя бы одну запись / указывать, какие таблицы соответствуют

Как указано выше, вы можете использовать LEFT OUTER JOIN дляобработать случай, когда нет совпадений ни в одной из 3 таблиц.Здесь я свернул выходные данные трех совпадений таблиц в другой CTE, а затем выполнил один последний LOJ между CTE с помощью coalesce, чтобы выделить место неудачного соединения (очевидно, вы также можете оставить это null,если требуется):

WITH cteUsers AS
(
    -- Replace with bob to see a match in 2 tables
    -- Replace with fred to see a match in 1 table.
    select user_id from users where email = 'missing@example.com' 
),
cteTables AS
(
  SELECT t1.user_id, 'MatchedTable1' as match, t1.othercol
  FROM table1 t1 INNER JOIN cteUsers cte on t1.user_id = cte.user_id
  UNION
  SELECT t2.user_id, 'MatchedTable2' as match, t2.othercol
  FROM table2 t2 INNER JOIN cteUsers cte on t2.user_id = cte.user_id
  UNION
  SELECT t3.user_id, 'MatchedTable3' as match, t3.othercol
  FROM table3 t3 INNER JOIN cteUsers cte on t3.user_id = cte.user_id
)
SELECT u.user_id, coalesce(match, 'Not Matched At All') as matched, t.othercol
FROM cteUsers u LEFT OUTER JOIN cteTables t ON u.user_id = t.user_id;

Я поставил SqlFiddle здесь , который, надеюсь, прояснит ситуацию. *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...