What's the difference between where clause and on clause when table left join?

后端 未结 6 1550
深忆病人
深忆病人 2020-11-27 18:28

SQL1:

select t1.f1,t2.f2 
from t1 
   left join t2 on t1.f1 = t2.f2 and t1.f2=1 and t1.f3=0 

SQL2:

select t1.f1,t2.f2 
from         


        
6条回答
  •  Happy的楠姐
    2020-11-27 19:14

    It is important to understand the logical order of SQL operations when thinking about SQL syntax. JOIN is an operator (and ON belongs to the relevant JOIN) in the FROM clause. The FROM clause is the first operation to be executed logically (optimisers can still choose to reorder things).

    In your example, there isn't really a difference, but it is easy to construct one, as I've shown in this blog post about the difference between ON and WHERE in OUTER JOIN (the example from the blog post uses the Sakila database):

    First query

    SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
    FROM actor a
    LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id
    WHERE fa.film_id < 10
    GROUP BY a.actor_id, a.first_name, a.last_name
    ORDER BY count(fa.film_id) ASC;
    

    Yields:

    ACTOR_ID  FIRST_NAME  LAST_NAME  COUNT
    --------------------------------------
    194       MERYL       ALLEN      1
    198       MARY        KEITEL     1
    30        SANDRA      PECK       1
    85        MINNIE      ZELLWEGER  1
    123       JULIANNE    DENCH      1
    

    Because we filtered the outer joined table in the WHERE clause, the LEFT JOIN was effectively turned into an INNER JOIN. Why? Because if we had an actor that didn't play in a film, that actor's only row would have fa.film_id IS NULL, and the fa.film_id < 10 predicate would thus yield NULL. Such actors are excluded from the result, just as with an INNER JOIN.

    Second query

    SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
    FROM actor a
    LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id
      AND fa.film_id < 10
    GROUP BY a.actor_id, a.first_name, a.last_name
    ORDER BY count(fa.film_id) ASC;
    

    Yields:

    ACTOR_ID  FIRST_NAME  LAST_NAME     COUNT
    -----------------------------------------
    3         ED          CHASE         0
    4         JENNIFER    DAVIS         0
    5         JOHNNY      LOLLOBRIGIDA  0
    6         BETTE       NICHOLSON     0
    ...
    1         PENELOPE    GUINESS       1
    200       THORA       TEMPLE        1
    2         NICK        WAHLBERG      1
    198       MARY        KEITEL        1
    

    Now, the actors without films are included in the result, because the fa.film_id < 10 predicate is part of the LEFT JOIN's ON predicate

    Conclusion

    Always place predicates where they make most sense logically.

    • Are they part of your JOIN operation? Place them in ON
    • Are they filters on your entire JOIN product? Place them in WHERE

提交回复
热议问题