tags:

views:

11940

answers:

3

I'm building a query with a GROUP BY clause that needs the ability to count records based only on a certain condition (field value is equal to 1).

SELECT
    UID, COUNT(UID) AS TotalRecords, SUM(ContractDollars) AS ContractDollars,

    --- Get the average of all records that satisfy the condition.
    (COUNTIF(MyColumn, 1) / COUNT(UID) * 100) are 1
FROM 
    dbo.AD_CurrentView
GROUP BY
    UID
HAVING
    SUM(ContractDollars) >= 500000

The COUNTIF() line obviously fails since there is no native SQL function called COUNTIF(), but the idea here is to determine the percentage of all rows that have the value '1' for MyColumn.

Any thoughts on how to properly implement this in a MS SQL 2005 environment?

+22  A: 

You could do:

select sum(case when myColumn=1 THEN 1 ELSE 0 END)
FROM AD_CurrentView

Edit:

Based on my test NULLS are not an issue but this is environment dependant. You could handle nulls such as:

select sum(case when isnull(myColumn,0)=1 THEN 1 ELSE 0 END)
FROM AD_CurrentView
JoshBerke
Nice. +1. Except that this would not work as intended if the column has nulls.
Learning
@Learning: Easy enough to change if the column has nulls. The part to focus on is the CASE statement.
casperOne
@casperOne : agreed but not sure if the null check is easy. any pointers?
Learning
case when nvl(myColumn,0) = 1 THEN 1 .....
Barry
It should work fine with the nulls. If I'm wrong you can always do an isnull(myColumn,0) but based on default ANSI settings on SQL2005 it should work
JoshBerke
+8  A: 

I usually do what Josh recommended, but brainstormed and tested a slightly hokey alternative that I felt like sharing.

You can take advantage of the fact that COUNT(ColumnName) doesn't count NULLs, and use something like this:

SELECT COUNT(NULLIF(0, myColumn))
FROM AD_CurrentView

NULLIF - returns NULL if the two passed in values are the same.

Advantage: Expresses your intent to COUNT rows instead of having the SUM() notation. Disadvantage: Not as clear how it is working ("magic" is usually bad).

Chris Shaffer
Now why didn't I think of this myself.Magic, indeed.
mavnn
Ah, brilliant. Just what I was looking for.
Damien
+2  A: 

I would use this syntax. It achives the same as Josh and Chris's suggestions, but with the advantage it is ANSI complient and not tied to a particular database vendor.

select count(case when myColumn = 1 then 1 else null end)
from   AD_CurrentView
asgeo1