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 здесь , который, надеюсь, прояснит ситуацию. *