'Postgresql Multiple counts for one table
From two columns in my table I want to get a unified count for the values in these columns. As an example, two columns are:
Table: reports
| type | place |
-----------------------------------------
| one | home |
| two | school |
| three | work |
| four | cafe |
| five | friends |
| six | mall |
| one | work |
| one | work |
| three | work |
| two | cafe |
| five | cafe |
| one | home |
If I do: SELECT type, count(*) from reports group by type
I get:
| type | count |
-----------------------------
| one | 4 |
| two | 2 |
| three | 2 |
| four | 1 |
| five | 2 |
| six | 1 |
Im trying to get something like this: (one rightmost column with my types grouped together and multiple columns with the count vales for each place) I get:
| type | home | school | work | cafe | friends | mall |
-----------------------------------------------------------------------------------------
| one | 2 | | 2 | | | |
| two | | 1 | | 1 | | |
| three | | | 2 | | | |
| four | | | | 1 | | |
| five | | | | 1 | 1 | |
| six | | | | | | 1 |
which would be the result of running a count like the one above for every place like this:
SELECT type, count(*) from reports where place = 'home'
group by type
SELECT type, count(*) from reports where place = 'school'
group by type
SELECT type, count(*) from reports where place = 'work'
group by type
SELECT type, count(*) from reports where place = 'cafe'
group by type
SELECT type, count(*) from reports where place = 'friends'
group by type
SELECT type, count(*) from reports where place = 'mall'
group by type
Is this possible with postgresql?
Thanks in advance.
Solution 1:[1]
you can use case
in this case -
SELECT type,
sum(case when place = 'home' then 1 else 0 end) as Home,
sum(case when place = 'school' then 1 else 0 end) as school,
sum(case when place = 'work' then 1 else 0 end) as work,
sum(case when place = 'cafe' then 1 else 0 end) as cafe,
sum(case when place = 'friends' then 1 else 0 end) as friends,
sum(case when place = 'mall' then 1 else 0 end) as mall
from reports
group by type
It should solve your problem
@S T Mohammed,
To get such type we can simply use using
after group
or where
condition in outer query, as below -
select type, Home, school, work, cafe, friends, mall from (
SELECT type,
sum(case when place = 'home' then 1 else 0 end) as Home,
sum(case when place = 'school' then 1 else 0 end) as school,
sum(case when place = 'work' then 1 else 0 end) as work,
sum(case when place = 'cafe' then 1 else 0 end) as cafe,
sum(case when place = 'friends' then 1 else 0 end) as friends,
sum(case when place = 'mall' then 1 else 0 end) as mall
from reports
group by type
)
where home >0 and School >0 and Work >0 and cafe>0 and friends>0 and mall>0
Solution 2:[2]
Answer by praktik garg is correct, it is not necessary to use else 0
:
SELECT type,
sum(case when place = 'home' then 1 end) as home,
sum(case when place = 'school' then 1 end) as school,
sum(case when place = 'work' then 1 end) as work,
sum(case when place = 'cafe' then 1 end) as cafe,
sum(case when place = 'friends' then 1 end) as friends,
sum(case when place = 'mall' then 1 end) as mall
FROM reports
GROUP BY type
You can also use the following even shorter syntax:
SELECT type,
sum((place = 'home')::int) as home,
sum((place = 'school')::int) as school,
sum((place = 'work' )::int) as work,
sum((place = 'cafe' )::int) as cafe,
sum((place = 'friends')::int) as friends,
sum((place = 'mall')::int) as mall
FROM reports
GROUP BY type
This will work because boolean true
is cast to 1
when condition is met.
Solution 3:[3]
You can use filter clause as well:
SELECT
type,
sum(1) FILTER (WHERE place = 'home') AS home,
sum(1) FILTER (WHERE place = 'school') AS school,
sum(1) FILTER (WHERE place = 'work') AS work,
sum(1) FILTER (WHERE place = 'cafe') AS cafe,
sum(1) FILTER (WHERE place = 'friends') AS friends,
sum(1) FILTER (WHERE place = 'mall') AS mall
FROM
reports
GROUP BY
type
Solution 4:[4]
You can use filter
and count
like this:
select type,
count(1) FILTER (where place = 'home') as home,
count(1) FILTER (where place = 'school') as school,
count(1) FILTER (where place = 'work') as work,
count(1) FILTER (where place = 'cafe') as cafe,
count(1) FILTER (where place = 'friends') as friends,
count(1) FILTER (where place = 'mall') as mall
from reports
group by type
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | crmpicco |
Solution 3 | wojtg |
Solution 4 | Mohamed Aymen Charrada |