• If you look at the execution plans for the two queries, the scalar function looks like the simpler plan. It simply has a clustered scan and a scalar operation. The scan is apparently the full cost of the execution. The other query shows two scans of the table, a hash match aggregate, and a merge join. Basically the optimizer is able to see into the table valued function and incorporate it's query into the plan for the outer query. Because it's able to generate a plan, it can make good choices in terms of performance. I set up the tests on my copy of AdventureWorks and saw the performance times go from 937ms to 78ms.

    The reads, according to SQL Trace, go from 374944 to 1253. Again, this has to come from getting an actual plan that seeks out appropriate data & joins it together as opposed to opening the table and checking each and every row, one by one.

    The only funny thing was, based on estimated plan cost, when the two scripts were run side by side, was 1% and the second plan was 99% even though the actual execution statistics went in exactly the opposite direction.

    "The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood"
    - Theodore Roosevelt

    Author of:
    SQL Server Execution Plans
    SQL Server Query Performance Tuning