SQL JOIN - WHERE clause vs. ON clause SQL JOIN - WHERE clause vs. ON clause sql sql

SQL JOIN - WHERE clause vs. ON clause


They are not the same thing.

Consider these queries:

SELECT *FROM OrdersLEFT JOIN OrderLines ON OrderLines.OrderID=Orders.IDWHERE Orders.ID = 12345

and

SELECT *FROM OrdersLEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID     AND Orders.ID = 12345

The first will return an order and its lines, if any, for order number 12345. The second will return all orders, but only order 12345 will have any lines associated with it.

With an INNER JOIN, the clauses are effectively equivalent. However, just because they are functionally the same, in that they produce the same results, does not mean the two kinds of clauses have the same semantic meaning.


  • Does not matter for inner joins

  • Matters for outer joins

    a. WHERE clause: After joining. Records will be filtered after join has taken place.

    b. ON clause - Before joining. Records (from right table) will be filtered before joining. This may end up as null in the result (since OUTER join).

Example: Consider the below tables:

  1. documents:

    idname
    1Document1
    2Document2
    3Document3
    4Document4
    5Document5
  2. downloads:

    iddocument_idusername
    11sandeep
    21simi
    32sandeep
    42reya
    53simi

a) Inside WHERE clause:

   SELECT documents.name, downloads.id     FROM documents     LEFT OUTER JOIN downloads       ON documents.id = downloads.document_id     WHERE username = 'sandeep'

For above query the intermediate join table will look like this.

id(from documents)nameid (from downloads)document_idusername
1Document111sandeep
1Document121simi
2Document232sandeep
2Document242reya
3Document353simi
4Document4NULLNULLNULL
5Document5NULLNULLNULL

After applying the WHERE clause and selecting the listed attributes, the result will be:

nameid
Document11
Document23

b) Inside JOIN clause

   SELECT documents.name, downloads.id   FROM documents     LEFT OUTER JOIN downloads       ON documents.id = downloads.document_id         AND username = 'sandeep'

For above query the intermediate join table will look like this.

id(from documents)nameid (from downloads)document_idusername
1Document111sandeep
2Document232sandeep
3Document3NULLNULLNULL
4Document4NULLNULLNULL
5Document5NULLNULLNULL

Notice how the rows in documents that did not match both the conditions are populated with NULL values.

After Selecting the listed attributes, the result will be:

nameid
Document11
Document23
Document3NULL
Document4NULL
Document5NULL


On INNER JOINs they are interchangeable, and the optimizer will rearrange them at will.

On OUTER JOINs, they are not necessarily interchangeable, depending on which side of the join they depend on.

I put them in either place depending on the readability.