简体   繁体   中英

How to display 0 if the count of distinct values is null?

My table has X distinct vendors,each of those vendors has Y objectives (including none)

vendor varchar2(100),
location varchar2(100),
type varchar2(100),
rating varchar2(20),
control_objective varchar2(1000)

now I need to display a bar graph that runs on the following script

select trim(vendor)||' '||trim(location)||' '||trim(type1) AS vendor_location,
       count(distinct control_objective) as "Cont Obj" 
from some_table
where (Rating = 'Needs improvement' or Rating = 'Unacceptable') and 
      "Year" = '2011' and 
      Quarter = 'Q3'
group by trim(vendor)||' '||trim(location)||' '||trim(type1)
order by trim(vendor)||' '||trim(location)||' '||trim(type1);

and produces the following output

-----vendor_location----Cont Obj
1----Big Blue Car---------5
2----Big Red Car----------4
3----Small Pink Truck-----4
4----Small White Truck----2

The problem is, there might be a 5th vendor, say Big White Van which has no values in the objective field hence it is not displayed. But I want it to be displayed as follows.

-----vendor_location----Cont Obj
1----Big Blue Car---------5
2----Big Red Car----------4
3----Small Pink Truck-----4
4----Small White Truck----2
5----Big White Van--------0

Reason being, the script feeds values into a bar graph, so I need the value 0 on the graph. I've tried several ways of overcoming this which is posted below

select trim(vendor)||' '||trim(location)||' '||trim(type1) AS vendor_location,
       count(distinct nvl(control_objective,0)) as "Cont Obj" 
from some_table
where (Rating = 'Needs improvement' or Rating = 'Unacceptable') and 
      "Year" = '2011' and 
      Quarter = 'Q3'
group by trim(vendor)||' '||trim(location)||' '||trim(type1)
order by trim(vendor)||' '||trim(location)||' '||trim(type1);

and

select trim(vendor)||' '||trim(location)||' '||trim(type1) AS vendor_location,
       (count(distinct control_objective)+0) as "Cont Obj" from some_table
where (Rating = 'Needs improvement' or Rating = 'Unacceptable') and 
      "Year" = '2011' and 
      Quarter = 'Q3'
group by trim(vendor)||' '||trim(location)||' '||trim(type1)
order by trim(vendor)||' '||trim(location)||' '||trim(type1);

and

select trim(vendor)||' '||trim(location)||' '||trim(type1) AS vendor_location,
       case when (count(distinct control_objective)<1) 
            then 0 
            else count(distinct control_objective) 
       end as "Cont Obj" 
from some_table
where (Rating = 'Needs improvement' or Rating = 'Unacceptable') and 
      "Year" = '2011' and 
      Quarter = 'Q3'
group by trim(vendor)||' '||trim(location)||' '||trim(type1)
order by trim(vendor)||' '||trim(location)||' '||trim(type1);

All the above attempts gave me the same output as I got earlier.

Honestly, I can't think of any more ways. The last option I have is to write the output into a table, and manually enter the missing values and then display the table. But this is really not what I want because the script should work for future quarters and years. So in the future some other value may be null and writing and reading into a table defeats the purpose of being "future-proof" so basically its not an option, just a quick-fix for the coming deadline.

I am using SQL Developer to test the scripts and the database is Oracle 11g

PS If it is not possible, do let me know. I'm even open to that being an answer!! I don't have much experience with SQL.

EDIT

Thank you all. I realised my problem on the way back home. The rating condition was not being satisfied, but couldn't post it until I got back home. Big thanks to Marcin!

You should see 'Big White Van' if it is in the table and the other fields (Rating , Year, Quarter) fulfill your condition. I guess you rather need something like this:

select trim(vendor) || ' ' || trim(location) || ' ' || trim(type1) AS vendor_location,
       count(distinct case
               when (Rating = 'Needs improvement' or Rating = 'Unacceptable') and "Year" = '2011' and Quarter = 'Q3' then
                control_objective
               else
                null
             end) as "Cont Obj"
  from some_table
 group by trim(vendor) || ' ' || trim(location) || ' ' || trim(type1)
 order by trim(vendor) || ' ' || trim(location) || ' ' || trim(type1);

which means: give me all vendor_locations and for each show me count of distinct control_objective values from those records for which (Rating = 'Needs improvement' or Rating = 'Unacceptable') and "Year" = '2011' and Quarter = 'Q3'

The reason it's not appearing is not because the value is null, it's because it's not fulfilling some other condition. Check that.

SELECT a, COUNT(DISTINCT b)
FROM (
    SELECT 'a' a, 'b' b FROM dual UNION ALL
    SELECT 'b', NULL FROM dual UNION ALL
    SELECT 'b', NULL FROM dual
)
GROUP BY a

->

b - 0
a - 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM