You can unpivot then pivot again to get the table you want as such:
input as ( select "data1" as data, "pass" as c1,"warn" as c2,"na" as c3, "pass" as c4 union all select "data2" as data, "na" as c1,"pass" as c2,"pass" as c3, "error" as c4 union all select "data3" as data, "warn" as c1,"pass" as c2,"na" as c3, "warn" as c4 union all select "data4" as data, "pass" as c1,"error" as c2,"pass" as c3, "error" as c4 union all select "data5" as data, "pass" as c1,"na" as c2,"na" as c3, "error" as c4 union all select "data6" as data, "pass" as c1,"warn" as c2,"na" as c3, "na" as c4 ), step_unpivot as ( select * from input unpivot(results for criterias in (c1,c2,c3,c4)) ) select * from step_unpivot pivot(count(data) for results in ('pass', 'warn','na','error'))
And since you want dynamic column selection for the unpivot(), you can probably use the answer to this question for that part: Dynamic UnPivot in Bigquery
Edit: Below a version with the dynamic unpivot
DECLARE myunpivot STRING; SET myunpivot = ( SELECT CONCAT('(', STRING_AGG( column_name, ','), ')'), From( SELECT column_name FROM dataset_name.INFORMATION_SCHEMA.COLUMNS where table_name ="unpivot_pivot" and column_name not in("data"))); EXECUTE IMMEDIATE format(""" with step_unpivot as ( select * from dataset_name.table_name unpivot(results for criterias in %s) ) select * from step_unpivot pivot(count(data) for results in ('pass', 'warn','na','error')) """, myunpivot);