30.06.2013 Views

SQL Server Team-based Development - Red Gate Software

SQL Server Team-based Development - Red Gate Software

SQL Server Team-based Development - Red Gate Software

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

333<br />

Chapter 11: <strong>SQL</strong> Refactoring<br />

The problem with the solution in Listing 11-10 is that it causes four reads of<br />

TestTable for every row returned by the outer SELECT statement (one read per<br />

column), with <strong>SQL</strong> <strong>Server</strong> storing the intermediate data in an internal Worktable<br />

(a temporary table in memory or tempdb).<br />

The refactoring is actually quite easy; we just have to think about this in a different way.<br />

We can place a condition somewhere other than in the WHERE clause. Can you guess<br />

where? If you said, "In the HAVING statement," you would be generally correct but, for this<br />

case, you would be wrong. The correct answer would be "In the SELECT statement." We<br />

must remember the good old CASE statement and think of a different way to aggregate<br />

our data.<br />

For the number column, the CASE statement evaluates to 1 when the condition is met<br />

and 0 when it's not, so, to get the count of the rows that match the condition, we simply<br />

have to sum over the returned values. The same logic applies to the other aggregates,<br />

and means that we don't need the correlated subqueries in the SELECT list and we only<br />

have to scan the table a single time to return all the data we need. Listing 11-11 shows the<br />

refactored reporting query.<br />

SELECT name ,<br />

SUM(CASE WHEN number % 2 = 0 THEN 1<br />

ELSE 0<br />

END) AS CountOfEvenNumbers ,<br />

SUM(CASE WHEN number % 2 = 0 THEN number<br />

ELSE 0<br />

END) AS SumOfEvenNumbers ,<br />

SUM(CASE WHEN type = 'F' THEN 1<br />

ELSE 0<br />

END) AS CountOfTypeF ,<br />

SUM(CASE WHEN name LIKE 'A%' THEN 1<br />

ELSE 0<br />

END) AS CountOfNamesStartingWithA<br />

FROM #TestTable<br />

GROUP BY name<br />

ORDER BY name

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!