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?