Terminology, visualization, example code, and column names - all slightly off target. The combination prevented you from finding proper solutions. Venn diagrams are **misleading** for the purpose. a_horse provided the perfect clue in [his comment][1]: > Venn diagrams do not visualize joins, but set operations like union, intersect or except. And his link to illustrate: - https://blog.jooq.org/2016/07/05/say-no-to-venn-diagrams-when-explaining-joins/ The example SQL is **misleading** on top of that. It starts with: SELECT * FROM ... That gets *all* columns from all joined tables. Not the expressed objective: > all organizations I'm either moderator or administrator. ### [`UNION`][2] Lennart offered a valid translation into SQL. Here's a shorter, more efficient one. The core query is: ```sql SELECT organization FROM admin_organization WHERE user = 10 UNION SELECT organization FROM moderator_organization WHERE user = 10 ``` `UNION`. Not `JOIN`. And not `UNION ALL` - we don't want duplicate organizations in the result. The column name `organization` is also **misleading** (IMHO). Should really be something like `organization_id` for clarity. The resulting set of unique IDs may already be all that's needed. To flesh it out with more (or all) attributes of the organization (columns of table `organization`), ***now*** you `JOIN` to the table: ```sql SELECT * FROM ( SELECT organization AS id FROM admin_organization WHERE user = 10 UNION SELECT organization FROM moderator_organization WHERE user = 10 ) x JOIN organization USING (id); ``` It's typically (substantially) cheaper to apply `UNION` on just the ID column, and then join. It may even be a necessity, if some of the columns have types have data types with no equality operator. More common than one might think. See: - https://dba.stackexchange.com/questions/274273/how-to-sum-the-values-of-a-json-column-filtered-with-regex/274276#274276 Assuming referential integrity, enforced with FK constraints, nothing is lost in the join. For *convenience*, it added a column alias in the subquery (`organization AS id`), so that we can use the simplified join condition with `USING (id)` which, in turn, allows us to use the simple (and now correct) `SELECT *` in the outer query to get all columns of the table `organization` without a duplicate ID column. ### Alternative with [`EXISTS`][3] Shorter equivalent that also avoids undue duplication or elimination of rows: ```sql SELECT * FROM organization o WHERE EXISTS (SELECT FROM admin_organization WHERE user = 10 AND organization = o.id) OR EXISTS (SELECT FROM moderator_organization WHERE user = 10 AND organization = o.id); ``` ### Naming convention A naming convention with **descriptive names** can avoid some of the confusion and noise. Use `organization_id` (or `org_id` if you prefer short names and there is no ambiguity) for all three: `admin_organization.organization`, `moderator_organization.organization`, and `organization.id`. [1]: https://dba.stackexchange.com/questions/274607/get-results-from-combined-either-inner-join#comment538544_274607 [2]: https://www.postgresql.org/docs/current/queries-union.html [3]: https://www.postgresql.org/docs/current/functions-subquery.html#FUNCTIONS-SUBQUERY-EXISTS