Question

I came across a query like this:

SELECT (SELECT COUNT(1) FROM Orders o WHERE i.ItemId = o.ItemId) [C]
FROM Items i

I changed it to following

;WITH cte_count
AS
(
    SELECT COUNT(1) c, OrderId FROM Orders Group By ItemId
)
SELECT a.c [Count], i.Name
FROM Items i
INNER JOIN cte_count c ON (c.ItemId = i.ItemId)

But the execution plan for both is same as shown below:

CTE and Inline Execution Plan

Similarly there was another query selecting TOP 1 Order By Id. I tried moving this one to CROSS APPLY But for this one as well I got same execution plans.

Cross Apply and Inline Execution Plan

Of course there were other joins and columns in query.

My dilemma is about utility and advantages of using CROSS APPLY and CTE. Are there any or its just exotic?

Was it helpful?

Solution

But the execution plan for both is same as shown below:

The plans are different. One is an inner join, the other is an outer join. The results may be the same in your simple test, but the semantics are different. In more complex queries, the difference may cause more obviously different execution plans, and come with a performance impact.

There are usually many ways to express the same requirement (or similar requirement, as in your example) in SQL. Which you use is initially a question of preference and style. In some cases, using one or the other will produce important performance differences because the declarative SQL takes a different code path through the optimizer. In this particular case, the outer join may play less well with the optimizer's exploration abilities (it has fewer tools to use with outer joins than inner joins).

Rewriting a query to define the same results using different syntax can be a valid tuning method, but it requires careful attention to detail and retesting whenever SQL Server is patched or upgraded. There is generally no reason to prefer one way of expressing a requirement in SQL over another.

In addition, as Andriy mentioned in a comment on the other copy of your question, "in the more general case, your inline queries will give you only one result per row, while joining to a CTE (which doesn't have to be a CTE, it could be a normal subselect) or CROSS APPLYing a row set can give you access to more than one column."

OTHER TIPS

My dilemma is about utility and advantages of using CROSS APPLY and CTE. Are there any or its just exotic?

For small datasets the optimizer is probably not bothering with extensive analysis. However, if one were to look at competing plans for large data sets (say millions of Orders or Items from your example), then CROSS APPLY, especially if Items are indexed, would execute quicker.

Moreover is this even appropriate to check it like this, using execution plan.

Sure. If there was a difference to be had, the plans would have shown. Moreover you would definitely notice performance differences upon execution.

What if you do

SELECT i.Name
       COUNT(o.OrderId) c
FROM   Items i
       JOIN Orders o ON i.ItemID = o.ItemID
GROUP BY i.ItemID

cte and apply has it's advantages in some cases i'm sure, just probably not simple cases like this

I like to use a cte mostly for aesthetic reasons when i'm trying to create a visual flow of how i'm breaking down larger results into smaller ones, for building the final query, and recursion ofcourse.

apply is pretty cool when you're using a table value function that takes a param value from the previous table. cross apply can be prettier than a full join statement.

if you know what you're looking for in a query plan it's just a matter of preference i suppose

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top