Search code examples
sqljoin

Difference between "and" and "where" in joins


Whats the difference between

SELECT DISTINCT field1 
  FROM table1 cd  
  JOIN table2 
    ON     cd.Company = table2.Name 
       and table2.Id IN (2728) 

and

SELECT DISTINCT field1 
  FROM table1 cd  
  JOIN table2 
    ON cd.Company = table2.Name 
 where table2.Id IN (2728) 

both return the same result and both have the same explain output


Solution

  • Firstly there is a semantic difference. When you have a join, you are saying that the relationship between the two tables is defined by that condition. So in your first example you are saying that the tables are related by cd.Company = table2.Name AND table2.Id IN (2728). When you use the WHERE clause, you are saying that the relationship is defined by cd.Company = table2.Name and that you only want the rows where the condition table2.Id IN (2728) applies. Even though these give the same answer, it means very different things to a programmer reading your code.

    In this case, the WHERE clause is almost certainly what you mean so you should use it.

    Secondly there is actually difference in the result in the case that you use a LEFT JOIN instead of an INNER JOIN. If you include the second condition as part of the join, you will still get a result row if the condition fails - you will get values from the left table and nulls for the right table. If you include the condition as part of the WHERE clause and that condition fails, you won't get the row at all.

    Here is an example to demonstrate this.

    Query 1 (WHERE):

    SELECT DISTINCT field1
      FROM table1 cd
      LEFT JOIN table2
        ON cd.Company = table2.Name
     WHERE table2.Id IN (2728);
    

    Result:

    field1
    200
    

    Query 2 (AND):

    SELECT DISTINCT field1
      FROM table1 cd
      LEFT JOIN table2
        ON cd.Company = table2.Name
       AND table2.Id IN (2728);
    

    Result:

    field1
    100
    200
    

    Test data used:

    CREATE TABLE table1 (Company NVARCHAR(100) NOT NULL, Field1 INT NOT NULL);
    INSERT INTO table1 (Company, Field1) VALUES
    ('FooSoft', 100),
    ('BarSoft', 200);
    
    CREATE TABLE table2 (Id INT NOT NULL, Name NVARCHAR(100) NOT NULL);
    INSERT INTO table2 (Id, Name) VALUES
    (2727, 'FooSoft'),
    (2728, 'BarSoft');