I’m trying to work out when a CROSS APPLY works out better, and I have to say it’s yet to convince me.
I have found one use case involving the most recent sales per customer. I can see that it is certainly slick and it enables me to get more than one sale per customer:
FROM #customers AS c CROSS APPLY (
    SELECT *
    FROM #sales AS s
    WHERE s.customerid=c.id
    ORDER BY s.date DESC OFFSET 0 ROWS FETCH FIRST 1 ROW ONLY
) AS s;
(I have fetched only one row for comparison purposes).
Using a CTE and multiple joins, I can get a similar result using:
WITH CTE(customer,last_order) AS (
    SELECT customerid, max(date)
    FROM #sales
    GROUP BY customerid
)
SELECT
    *
FROM
    #sales AS s
    JOIN cte ON s.customerid=cte.customer AND s.date=cte.last_order
    JOIN customers AS c ON s.customerid=c.id
;
which looks messier, and only gives me one sale per customer.
However, I find that the latter is much lest costly than the former. In my sample data, the CROSS APPLY costs 74% while the CTE with joins costs 26%. With a larger set of data I get 98% vs 2%.
I have set up a fiddle at https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=18b7cf86195a56552bacd7e985da898c .
Is there something wrong with the way I did my CROSS APPLY, or is it inherently more expensive?
