I’m working on a CTE (probably not relevant), and I have two possible inner joins, but the second one should only be used if the first one is empty (it could be used anyway, in fact, IT MUST be executed alongside the first inner join:
with recursive "test_table" as (
select stuff from test_table
inner join base_table bt on bt.property = test_table.property // THIS MIGHT FIND A SET OF ROWS
inner join base_table bt2 on bt2.id = test_table.innerProperty // THIS MIGHT FIND SOME OTHER ROWS
)
The thing is, this doesn’t work, as it brings 0 rows, but if I execute the first inner join OR the second one separetely, it works just fine. I tried using an OR
but it loops infinitely.
I’m using postgres 13, btw
2
Answers
INNER JOIN
only keeps rows that meet the join condition on both sides, and in that sense it acts like a filter. When you have two inner joins, you are performing this filter twice, so when you get 0 rows returned it means that no row meets both of the 2 join conditions you used.If I understand your question correctly, rather than do 2 inner joins, you should opt for 2 left joins and use
COALESCE
to set the condition that when the first join didn’t produce any results, use the second join.Assuming some sample data on your structures:
I think in general using left outer joins instead of inner joins is the basis of the solution:
Where the
where
clause mimics basically what you are trying to do — you want a match from one or the other.However, this yields these results:
My understanding is that if there is a match on
bt
then you don’t want to even evaluate the second join — makebt2
conditional on NO match frombt
. If that is the case you can simply change the join condition onbt2
from this:to this:
Meaning, don’t do the BT2 join if BT was successful.
Which you can see skips removes bt2.stuff = pancake from the query:
Let me know if this is what you had in mind.