Reputation: 19
I have a first table called emails with a list of all the emails of my colleagues
| email |
| ----------------------- |
| [email protected] |
| [email protected] |
| [email protected] |
| [email protected] |
I have a second table called aliases, with a list of all the secondary emails/aliases my colleagues are using
| alias1 | alias2 |
| ------------------------ | ------------------- |
| [email protected] | [email protected] |
| [email protected] | [email protected] |
| [email protected] | [email protected] |
| [email protected] | [email protected] |
| [email protected] | [email protected] |
| [email protected] | [email protected] |
I can see that the users [email protected] and [email protected] are using aliases. But let's focus on the user [email protected].
I need to get a list of all the email addresses the user [email protected] is using. The difficult part is that I need to get a list with the main email address plus all the intersections where the first email and consecutive ones are being used by this user. The end result should look like this
| emails |
| ------------------- |
| [email protected] |
| [email protected] |
| [email protected] |
| [email protected] |
| [email protected] |
| [email protected] |
If I do WHERE email='[email protected]'
it should look like this, but I also need the same result if I do
WHERE email='[email protected]'
I've been through some days of testing queries and I don't seem to have a solution for this (I've been using right joins, full outer joins and unions, but no luck so far). Is there a good way to do this?
Upvotes: 0
Views: 49
Reputation: 48770
You can use a recursive CTE to walk the graph and get the full list of interconnected aliases. Care needs to be taken to handle cycles; that requires the query to use UNION
instead of the traditional UNION ALL
to separate the anchor and recursive member of the CTE.
The query can take the form:
with recursive
n as (
select '[email protected]' as email
union
select case when a.alias1 = n.email then a.alias2 else a.alias1 end
from n
join aliases a on (a.alias1 = n.email or a.alias2 = n.email)
and a.alias1 <> a.alias2
)
select * from n;
Result:
email
-------------------
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
See running example at DB Fiddle.
Upvotes: 1