Question

I wasn't able to come up with the right keywords to search for the answer for this, so apologies if it was answered already.

Consider the following SQL view:

CREATE VIEW View1 AS
SELECT Column1
      ,Column2
      ,(SELECT SUM(Column3) FROM Table2 WHERE Table2.ID = Table1.ID)  -- Subquery
FROM Table1

If I run the following query, will the subquery be executed or does SQL Server optimise the query?

SELECT Column1 FROM View1

I'm looking at this from a performance point of view, say, if the view has quite a few subqueries (aggregations can take a long time if the inner select refers to a large table).

I'm using SQL Server 2008 R2, but I'm interested to know if the answer differs for 2012 or maybe MySQL.

Thanks.

Was it helpful?

Solution

As has been said, this varies depending on your DBMS (version and provider), to know for sure check the execution plan. This shows for SQL-Server 2008 the subquery is not executed:

enter image description here

As you can see in the top plan where Column3 is not selected the plan is simply selecting from table1, in the bottom plan that in includes Column3, table2 is queried.

In SQL-Server 2008 R2 it is not executed.

In SQL-Server 2012 it is not executed;

In MySQL it is executed, and both queries generate the same plan:

enter image description here

To elaborate further, it will also depend on your exact query, as well as your DBMS. For example:

CREATE VIEW View2
AS
    SELECT  t.ID, t.Column1, t.Column2, t2.Column3
    FROM    Table1 t
            LEFT JOIN
            (   SELECT  ID, Column3 = SUM(Column3)
                FROM    Table2
                GROUP BY ID
            ) t2
                ON t2.ID = t.ID
GO
SELECT  Column1, Column2
FROM    View2;

SELECT  Column1, Column2, Column3
FROM    View2;

enter image description here

In this case you get similar results to the correlated subquery, The plan shows only a select from table1 if column3 is not selected, because it is a LEFT JOIN the optimiser knows that the subquery t2 has no bearing on the select from table1, and no columns are used so it does not bother with it. If you changed the LEFT JOIN to an INNER JOIN though, e.g.

CREATE VIEW View3
AS
    SELECT  t.ID, t.Column1, t.Column2, t2.Column3
    FROM    Table1 t
            INNER JOIN
            (   SELECT  ID, Column3 = SUM(Column3)
                FROM    Table2
                GROUP BY ID
            ) t2
                ON t2.ID = t.ID
GO
SELECT  Column1, Column2
FROM    View3;

SELECT  Column1, Column2, Column3
FROM    View3;

enter image description here

The query plan for these two queries shows that because the aggregate column is not used in the second query, the optimiser essentially changes the view to this:

SELECT  t.ID, t.Column1, t.Column2
FROM    Table1 t
        INNER JOIN
        (   SELECT  DISTINCT ID
            FROM    Table2
        ) t2
            ON t2.ID = t.ID;

As seen by the appearance of the Distinct Sort on table2 and the removal of the Stream Aggregate.

So to summarise, it depends.

OTHER TIPS

The view is just a definition, like a temporary table in a query. First the query behind the view will be executed and then your selection on the view. So yes the subquery will be executed. If you don't want this you should create a new view without the subquery.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top