Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prioritize JOIN on multiple columns with an OR

I'm trying to track the source of comments on a blog site and my question relates to priority JOINing on multiple columns with an OR statement.

The comments table:

      Column        |          Type
--------------------+-------------------------
 id                 | integer
 text               | character varying(1024)
 session_source_id  | integer
 user_source_id     | integer

If I have a query like so:

SELECT s.type, COUNT(c.id) FROM comments c
   LEFT JOIN sources s ON (c.session_source_id = s.id OR c.user_source_id = s.id) 
GROUP BY 1;

There are situations where we know the user source but NOT the session source (which is why I used OR), but I want to prioritize the session_source_id if we also have a user_source_id and those two ids differ.

(there are also situations where we don't know either sources and both columns are null, hence the LEFT JOIN)

Does that query prioritize the JOIN on session_source_id since it's listed first in the joining OR statement? How does Postgres handle OR conditionals in JOIN statements?

like image 696
dizzyf Avatar asked Oct 31 '16 15:10

dizzyf


People also ask

Does the order of join columns matter?

No, it doesn't matter.

Does order matter in a join on clause?

The order of the conditions in the ON clause doesn't matter. The queries per query pair you are showing are equal. If one query in a pair gives you different rows than the other, then this cannot be caused by the queries you are showing.

Can Join be done on multiple columns?

If you'd like to get data stored in tables joined by a compound key that's a primary key in one table and a foreign key in another table, simply use a join condition on multiple columns. In one joined table (in our example, enrollment ), we have a primary key built from two columns ( student_id and course_code ).

Can we use multiple columns in where clause?

If you want compare two or more columns. you must write a compound WHERE clause using logical operators Multiple-column subqueries enable you to combine duplicate WHERE conditions into a single WHERE clause.


2 Answers

Posting GarethD's comment as answer and Wiki, so that it won't be lost:

Try COALESCE instead of OR...

LEFT JOIN sources s 
ON s.id = COALESCE(c.session_source_id, c.user_source_id)
like image 198
2 revs, 2 users 83% Avatar answered Oct 06 '22 18:10

2 revs, 2 users 83%


Using OR won't prioritize the conditions, if both conditions are true, both records will be returned.
If you want any priority, you can use CASE EXPRESSION which will break the moment a condition is met :

SELECT s.type, COUNT(c.id) FROM comments c
LEFT JOIN sources s 
 ON (CASE WHEN c.session_source_id = s.id THEN 1
          WHEN c.user_source_id = s.id THEN 1
          ELSE 0
     END = 1) 
GROUP BY 1;
like image 45
sagi Avatar answered Oct 06 '22 18:10

sagi