Home > Software engineering >  How to create a table to count with a conditional
How to create a table to count with a conditional

Time:12-29

I have a database with a lot of columns with pass, fail, blank indicators I want to create a function to count each type of value and create a table from the counts. The structure I am thinking is something like enter image description here where x,y, etc are columns from another table.

I don't know which could be the best approach for this thank you all in advance

I tried this structure but it shows syntax error

CREATE FUNCTION Countif (columnx nvarchar(20),value_compare nvarchar(10))
RETURNS Count_column_x AS
BEGIN
    IF columnx=value_compare
    count(columnx)
END
RETURN
END

Also, I don't know how to add each count to the actual table I am trying to create

CodePudding user response:

I think you don't need a generic solution like a function with value as parameter.

Perhaps, you could create a view grouping your data and after call this view filtering by your value.

Your view body would be something like that

select value, count(*) as Total
from table_name
group by value

Feel free to explain your situation better so I could help you.

CodePudding user response:

You can do this by grouping by the status column.

select status, count(*) as total
from some_table
group by status

Rather than making a whole new table, consider using a view. This is a query that looks like a table.

create view status_counts as
  select status, count(*) as total
  from some_table
  group by status

You can then select total from status_counts where status = 'pass' or the like and it will run the query.


You can also create a "materialized view". This is like a view, but the results are written to a real table. SQL Server is special in that it will keep this table up to date for you.

create materialized view status_counts with distribution(hash(status))
  select status, count(*) as total
  from some_table
  group by status

You'd do this for performance reasons on a large table which does not update very often.

CodePudding user response:

Conditional counting (or any conditional aggregation) can often be done inline by placing a CASE expression inside the aggregate function that conditionally returns the value to be aggregated or a NULL to skip.

An example would be COUNT(CASE WHEN SelectMe = 1 THEN 1 END). Here the aggregated value is 1 (which could be any non-null value for COUNT(). (For other aggregate functions, a more meaningful value would be provided.) The implicit ELSE returns a NULL which is not counted.

For you problem, I believe the first thing to do is to UNPIVOT your data, placing the column name and values side-by-side. You can then group by value and use conditional aggregation as described above to calculate your results. After a few more details to add (1) a totals row using WITH ROLLUP, (2) a CASE statement to adjust the labels for the blank and total rows, and (3) some ORDER BY tricks to get the results right and we are done.

The results may be something like:

SELECT
    CASE
        WHEN GROUPING(U.Value) = 1 THEN 'Total'
        WHEN U.Value = '' THEN 'Blank'
        ELSE U.Value
        END AS Value,
    COUNT(CASE WHEN U.Col = 'x' THEN 1 END) AS x,
    COUNT(CASE WHEN U.Col = 'y' THEN 1 END) AS y
FROM @Data D
UNPIVOT (
  Value
  FOR Col IN (x, y)  
) AS U
GROUP BY U.Value WITH ROLLUP
ORDER BY
    GROUPING(U.Value),
    CASE U.Value WHEN 'Pass' THEN 1 WHEN 'Fail' THEN 2 WHEN '' THEN 3 ELSE 4 END,
    U.VALUE

Sample data:

x y
Pass Pass
Pass Fail
Pass
Fail

Sample results:

Value x y
Pass 3 1
Fail 1 1
Blank 0 2
Total 4 4

See this db<>fiddle for a working example.

  • Related