4

shelter_inventory (table)

gid | pav_type | yes
 1  |  1       | 1
 2  |  1       | 1
 3  |  0       | 1
 4  |  2       | 1 
 5  |  2       | 0

this is the current query (does not display count = 0)

SELECT pav_type, count(*) FROM shelter_inventory 
WHERE yes = 1 GROUP BY pav_type ORDER BY pav_type

and I want the result to display like this

pav_type | count(*)
 0       |  1
 1       |  2
 2       |  1 
 3       |  0

How could I query on this case? I use PostgreSQL.

3
  • 1
    Your example table does not have a pav_type of value 3 so it will never show up in the group by. Do you have a separate table that defines the pav_types? Commented Jul 17, 2011 at 3:30
  • your query looks good for me.. if u would have had the row for pav_type 3 in ur table you will have that Commented Jul 17, 2011 at 3:32
  • no, pav_type is simple like that (0,1,2,3) Commented Jul 17, 2011 at 4:54

3 Answers 3

4

If your pav_type values are sequential, then you could use generate_series in place of an external table:

select p.pav_type, count(yes)
from generate_series(0,3) as p(pav_type)
left outer join shelter_inventory s
  on p.pav_type = s.pav_type and s.yes = 1
group by p.pav_type
order by p.pav_type

This yields:

 pav_type | count 
----------+-------
        0 |     1
        1 |     2
        2 |     1
        3 |     0

This:

generate_series(0,3) as p(pav_type)

essentially generates an inlined table with a single column called pav_type and four rows: 0, 1, 2, 3. And you need to have the s.yes = 1 in the join condition (rather than the WHERE) because you want the yes = 0 values to be in the pre-grouped result set; if s.yes = 1 is in the WHERE clause then the yes = 0 rows won't be counted regardless of what the join condition is.

If your pav_types do not nicely fit with generate_series (i.e. not sequential or step-sequential) and you only have a small number of them, you could join to a VALUES expression:

select p.pav_type, count(yes)
from (values (0), (1), (2), (3)) as p(pav_type)
left outer join shelter_inventory s
  on p.pav_type = s.pav_type and s.yes = 1
group by p.pav_type
order by p.pav_type

You need to make sure you get all the parentheses in the right places of course.

If you do have the pav_types in a separate table then do a LEFT OUTER JOIN to that table instead of using the generate_series. If your pav_types are not sequential and you have too many to sensibly put in a VALUES expression, then build a table to hold the valid pav_type values and LEFT OUTER JOIN to that.

Sign up to request clarification or add additional context in comments.

2 Comments

+1 I never knew about generate_series()! Thanks for posting :)
@Bohemian: I learned about generate_series the same way you just did :)
0

Use SUM(CASE WHEN yes=1 THEN 1 ELSE 0 END), you can also include GROUP BY pav_type HAVING SUM(CASE WHEN yes=1 THEN 1 ELSE 0 END) = 0

Comments

0

You need a separate table with all pav_type values in it, let's name it pav_type_ref. Then outer join from it.

create table pav_type_ref (pav_type int);
insert into pav_type_ref values (1), (2), (3);

SELECT r.pav_type, sum(case when i.pav_type is null then 0 else 1 end)
FROM pav_type_ref r
left join shelter_inventory i on i.pav_type = r.pav_type
WHERE yes = 1
GROUP BY 1
ORDER BY 1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.