65.9K
CodeProject is changing. Read more.
Home

Conditional Sums in SQL Aggregate Methods

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1 vote)

Jan 5, 2012

CPOL

2 min read

viewsIcon

60288

Count the records in a table which are of a certain type.

One thing that you may encounter frequently is a situation where you want to count the records in a table which are of a certain type. You want to do this as efficiently as possible, instead of running a new count query for each type. Let’s use the below table for reference.

Name Type Age
Buffy Dog 10
Dusty Dog 13
Clyde Dog 2
Bonnie Cat 1
Milky Ferret 1

We have above a table of animals. How can we determine the count of each type of animal? Perhaps the most direct method that comes to mind is to run a COUNT() query for each type of animal. This would mean we have 3 queries to run, as there are 3 types of animals, and a fourth to get the results.

DECLARE @numdogs INT
DECLARE @numcats INT
DECLARE @numferrets INT
 
SELECT @numdogs = COUNT(*) FROM animals WHERE TYPE = 'Dog'
SELECT @numcats = COUNT(*) FROM animals WHERE TYPE = 'Cat'
SELECT @numferrets = COUNT(*) FROM animals WHERE TYPE = 'Ferret'
 
SELECT @numdogs AS NumDogs, @numcats AS NumCats, @numferrets AS NumFerrets

We will get results from that query like this.

NumDogs NumCats NumFerrets
3 1 1

A method to simplify this query and to run within a single select that I have used with success is to use a “conditional” sum in the SQL query. So rather than running COUNT(*) we will be running SUM(…). We will combine the SUM() call with a CASE statement, so that it counts correctly. This is the trick I hope to teach you, which you may not have considered before: you can place CASE … END statements inside of aggregate functions.

Throw away all of our temporary variables, the 4 Select statements involved, and let’s replace them with this single select.

SELECT 
	SUM(CASE WHEN TYPE='Dog' THEN 1 ELSE 0 END) AS NumDogs,
	SUM(CASE WHEN TYPE='Cat' THEN 1 ELSE 0 END) AS NumCats,
	SUM(CASE WHEN TYPE='Ferret' THEN 1 ELSE 0 END) AS NumFerrets
FROM 
	animals

We get these results:

NumDogs NumCats NumFerrets
3 1 1

Which is exactly what we got previously, but using a much simpler method. The trick was to insert a CASE … END statement inside the SUM. The case will return a 1 when the type is the type we are looking for, and a 0 otherwise. The sum will then execute to add up all of those 0s and 1s. A 0 will not add anything, so we will effectively end up counting the values which match the type we are looking for.