views:

431

answers:

3

Using Reporting Services in SQL Server 2005: Is there a way to count only records that are not null; similar to "COUNTA" in Excel? I would think this would be very simple process, but nothing I have tried has worked. For example, I have tried using the following expression for "Completed", which is one column I am trying to count: =count(IIF(Fields!Completed.Value="END")) However, this throws the "wrong number of arguments" error. "Completed" will have a value of "End" or be null.

If necessary, I can try to work this into my SQL query, but the query is already incredibly complicated.

Also, I've found very little documentation for how to calculate report totals, and how to total from groups. Would anyone have any recommendations on what to use as a reference?

Update: upon further inspection, the expression =SUM(IIF(IsNothing(Fields!Completed.Value),0,1)) DOES indeed return the appropriate number of records. I made the mistake of thinking that the report would tally up the number of records in the actual report with "end" for a value. Since the report groups on "Completed", "End" only shows up once in the report for each unique ID (also being grouped on, above Completed). So I really need to be counting (suming?) based on subtotals...if that's even possible.

+1  A: 

Generally, if you are trying to sum a column value then you must remember that NULL + anything is NULL. So to get around this, you can do something like:

SELECT SUM(coalesce(col1,0)) col1Sum
  FROM your_table
 WHERE <conditions>

What that code does is make sure that if col1 has a NULL value, we make it 0 before trying to sum so that we will always get a valid sum result.

So when doing things like getting report totals, etc., it's important to remember this step when summing up your values.

As for getting records that are NOT NULL, you need to define what that means. Does that mean "every column in the row must be NOT NULL", only certain ones, etc?

In general, you can check a column for not null by issuing:

SELECT *
  FROM your_table
 WHERE col1 IS NOT NULL

You would need to repeat that WHERE clause condition for all columns you want to not be NULL.

dcp
The first query could also be written as `SELECT SUM(ISNULL(COL1,0))...`
eidylon
@eidylon - Yes, they are equivalent in this example.
dcp
Ok, but I'm trying to count only null values in the report, as opposed to the SQL statement...unless there is a way to plug this into the report outside of the SQL statement on the Data tab? I've been advised to not use subreports, if that's what you were thinking of.
To reiterate from the post below, the column I am trying to count (not sum) will either have a value of "end", or it will be null.
@user329266 - I don't really understand what the difference between "null values in the report" and "null values in the data" is. If you want get a count of the number of times a given column is null, then you could just do "SELECT COUNT(*) FROM your_table WHERE col1 IS NULL". Maybe you can edit your question and supply some real data and what you are expecting as output.
dcp
DCP, I've rephrased the original question. I had put "SQL Server 2005 Reporting Services" in the title of the question - guess I needed to reiterate that a few more times. Reporting Services is really the same thing as if you create a report in Visual Studio. At this point, I would prefer not to alter the query being used in the report, which is very complicated, and I won't paste it here because of security concerns.
+1  A: 
=SUM(IIF(IsNothing(Fields!Completed.Value),0,1))
Kenneth
This does not work. The column I am trying to count will either have a value of "end", or it will be null. So CountDistinct returns only one value.
Should do exactly what you need now.
Kenneth
Thanks, Kenneth. I tried your revised expression, but the result is closer to the total number of null values than to the number of non null values. Trying to figure out what the opposite of "IsNothing" might be.
Kenneth
Just tried swapping the 0 and 1. Also tried using Count and not Sum, since I want the total count of results that are not null. Results are the same when I swap 0 with 1 as they are in their original positions. Just for the sake of trying something different, I also tried Sum, with 0 and 1 in the originaly positions and then swapped. Neither returns the correct results. Yes, this is Reporting Services 2005.
Kenneth
Good question...If I run the query from my data tab in SQL Server 2005, the results that come up are either "End" or NULL. But in RS, I'm grouping on the "Completed" column, and trying to count the total for Completed in the footer, so...you're saying that if the report is grouped, it's given a value regardless? Argh! Will need to try dumping the results in a table object as suggested...
Ok...upon further inspection, the expression above DOES indeed return the appropriate number of records. I made the mistake of thinking that the report would tally up the number of records *in the actual report* with "end" for a value. Since the report groups on "Completed", "End" only shows up once in the report for each unique ID (also being grouped on, above Completed). So I really need to be counting (suming?) based on subtotals...if that's even possible.
Marking this as the correct answer because it is the closest. I ended up revising my query to ony pull in one record for each ID so I don't have duplicate rows that the report tries to total. Even so...one would think that reporting software would have an easier system of calculating totals. Oh well.
A: 

In your last comment you say "I really need to be counting (suming?) based on subtotals...if that's even possible"

A way that I work around this in SSRS is to compute a dataset for the report which has columns for my subtotal values. Basically I precalculate the subtotals, and then I have those values available everywhere in my report. This can be done in a report datamart, or in the stored procedure that produces the dataset. Although this is kind of awkward, I find that it is sometimes easier than trying to bend SSRS to my will. Thought I would mention it in case it is useful.

You can execute this code to get a visual for what I mean -

-- use this code to create a sample data set 
-- Note that I am simply stuffing the correct subtotal values in - 
-- but in reality, you would calculate these from your base data
CREATE TABLE SampleDataSet( Salesperson varchar(50), Region varchar(20), 
Country varchar(30), Sales float, RegionSales float, CountrySales float, GrandTotalSales float ) 

INSERT INTO SampleDataSet Values( 'Brown', 'East', 'Canada', 1000.40, 6780.00, 108686.56, 705043.89 ) 
INSERT INTO SampleDataSet Values( 'Smith', 'East', 'Canada', 3420.76, 6780.00, 108686.56, 705043.89 ) 
INSERT INTO SampleDataSet Values( 'Williams', 'East', 'Canada', 2358.84, 6780.00, 108686.56, 705043.89 ) 
INSERT INTO SampleDataSet Values( 'Simons', 'West', 'Canada', 6298.68, 101906.56, 108686.56, 705043.89 ) 
INSERT INTO SampleDataSet Values( 'Miller', 'West', 'Canada', 95607.88, 101906.56, 108686.56, 705043.89 )
INSERT INTO SampleDataSet Values( 'Knight', 'North', 'UK', 596357.33, 596357.33, 596357.33, 705043.89 ) 

-- inspect data 
SELECT * FROM  SampleDataSet

SELECT Region, SUM(Sales) as RegionSales FROM  SampleDataSet
GROUP BY Region

SELECT Country, SUM(Sales) as CountrySales FROM  SampleDataSet
GROUP BY Country

SELECT SUM(Sales) as GrandTotalSales FROM  SampleDataSet
soo