SQL JOIN: is there a difference between USING, ON or WHERE?

前端 未结 6 1843
渐次进展
渐次进展 2020-11-22 00:11

I was wondering if there is any difference in the way SQL performs on these join statements:

SELECT * FROM a,b WHERE a.ID = b.ID

SELECT * FROM a JOIN b ON a         


        
相关标签:
6条回答
  • 2020-11-22 00:55

    This is a duplicate of this SO question: Explicit vs implicit SQL joins. Generally I think the implicit (where version) is bad form and not as clear as the explicit (on version). I also think the implicit is being depreciated but not 100% on that one. The execution plan is the same for both though.

    0 讨论(0)
  • 2020-11-22 01:01

    No one has provided an answer about the USING(...) syntax yet.

    While these two queries are equivalent logically, and also from the perspective of most modern optimisers:

    SELECT * FROM a, b WHERE a.id = b.id
    SELECT * FROM a JOIN b ON a.id = b.id
    

    This one has a slightly different semantics:

    SELECT * FROM a JOIN b USING (id)
    

    Assuming the following schema:

    CREATE TABLE a (id int, a1 int, a2 int);
    CREATE TABLE b (id int, b1 int, b2 int);
    

    The first two queries will have their asterisks expanded to:

    SELECT a.id, a.a1, a.a2, b.id, b.a1, b.a2 FROM ...
    

    Whereas the third query will have its asterisk expanded to:

    SELECT coalesce(a.id, b.id) AS id, a.a1, a.a2, b.a1, b.a2 FROM ...
    

    This is quite different for various reasons, including:

    • The number of projected columns is now 5 instead of 6. This could get in the way when you use UNION or other set operations. Which you probably don't, with an asterisk.
    • There is no longer a qualified (and duplicate) a.id or b.id column, only an id column. While PostgreSQL still allows for qualifying references to id (e.g. when needing to disambiguate them), Oracle for example doesn't.
    • As a consequence, in the third query with the USING(...) syntax, projecting a.* or b.* is no longer possible in Oracle.
    0 讨论(0)
  • 2020-11-22 01:04

    There is no difference in performance.

    However, the first style is ANSI-89 and will get your legs broken in some shops. Including mine. The second style is ANSI-92 and is much clearer.

    Examples:

    Which is the JOIN, which is the filter?

    FROM T1,T2,T3....
    WHERE T1.ID = T2.ID AND
         T1.foo = 'bar' AND T2.fish = 42 AND
         T1.ID = T3.ID
    
    FROM T1 
       INNER JOIN T2 ON T1.ID = T2.ID
       INNER JOIN T3 ON T1.ID = T3.ID
    WHERE
       T1.foo = 'bar' AND T2.fish = 42
    

    If you have OUTER JOINs (=*, *=) then the 2nd style will work as advertised. The first most likely won't and is also deprecated in SQL Server 2005+

    The ANSI-92 style is harder to bollix too. With the older style you can easily end up with a Cartesian product (cross join) if you miss a condition. You'll get a syntax error with ANSI-92.

    Edit: Some more clarification

    • The reason for not using "join the where" (implicit) is the dodgy results with outer joins.
    • If you use explicit OUTER JOINs + implicit INNER JOINs you'll still get dodgy results + you have inconsistency in usage

    It isn't just syntax: it's about having a semantically correct query

    Edit, Dec 2011

    SQL Server logical query processing order is FROM, ON, JOIN, WHERE...

    So if you mix "implicit WHERE inner joins" and "explicit FROM outer joins" you most likely won't get expected results because the query is ambiguous...

    0 讨论(0)
  • 2020-11-22 01:05

    See this

    INNER JOIN ON vs WHERE clause

    0 讨论(0)
  • 2020-11-22 01:06

    The difference is readability and maintainability. SELECT * FROM a JOIN b ON a.ID = b.ID conveys your exact intent, all in the same place.

    I won't say definitively since I haven't gotten under the hood of the last query optimizer, but I'm pretty confident you're looking at a trivial difference in performance, if any.

    0 讨论(0)
  • 2020-11-22 01:11

    I despise when you force a join by using WHERE. It just doesn't to me look right, a dirty hack. Proper ANSI join is to use ON:

    SELECT 
        p.Product,
        o.Order
    FROM 
        Product p
    INNER JOIN
        Order o
    ON
        o.OrderID = p.OrderID
    

    Prefer using ON when joining and WHERE to filter results. Remember WHERE is one of the last things you will use besides grouping and order by where you want to filter your results. So you shouldn't join your tables using WHERE as it is much difficult to read.

    SELECT 
        p.Product,
        o.Order
    FROM 
        Product p
    INNER JOIN
        Order o
    ON
        o.OrderID = p.OrderID
    WHERE
        o.Category = 'IT'
    

    In the end you (the developer) might not be around in the future so readability and maintainability will help the pour soul who has to take over your code :).

    When I see developers use WHERE to join their tables it's usually an indication that they don't know enough T-SQL. That is my personal opinion.

    0 讨论(0)
提交回复
热议问题