Sql Nested group by - sql

Following query returns a number of people having the same name with gender = Male.
select lookup_name.firstname,count(lookup_name.firstname)
from lookup_name
where gender='M'
group by firstname
similarly, the query below returns a number of people having the same name with gender = Female.
select lookup_name.firstname,count(lookup_name.firstname)
from lookup_name
where gender='F'
group by firstname
I need to write a query which finds out the name and tell the gender (whether male or female) with the greater count. i.e higher probability of that name in the database is of being male or female?

SELECT firstname, Male, Female,
case when Male=Female then 'indeterminate'
when Male>Female then 'probably male'
else 'probably female' end MostProbablySex
FROM (
select firstname,
SUM(case when gender='M' then 1 else 0 end) Male,
SUM(case when gender='F' then 1 else 0 end) Female
from lookup_name
group by firstname
) X;
Or a single pass:
select firstname,
CASE SIGN(2.0 * SUM(case when gender='M' then 1 else 0 end) / COUNT(*) - 1)
WHEN -1 then 'probably female'
WHEN 0 then 'indeterminate'
WHEN 1 then 'probably male'
END
from lookup_name
group by firstname;

Related

print out the number of two values in the same column

I have a database in which there are people. They have genders. How would I count male and female separate.
SELECT count(id_osb)
from ds_osebe
where spol = 'M'
or spol = 'Z';
this is how i can get the number of male and female combined
I do not know how to make this, it's my second day learning this.
You need to use grouping (group by)
SELECT spol, count(id_osb)
from ds_osebe
where spol = 'M'
or spol = 'Z'
group by spol
NOTE: replace spol if it doesn't denote sex
You can use a CASE expression.
Query
select SUM(case spol when 'M' then 1 else 0 end) as male_cnt
SUM(case spol when 'Z' then 1 else 0 end) as female_cnt
from ds_osebe;
select count(1) over (partition by spol) as qty, spol
from ds_osebe
/*if you have more than 2 gender options*/
where spol in ('Z', 'M');

Is it possible to combine these two sql statements into one statement using group by?

select client_type, count(gender) as num_males
from clients
where gender = 'Male'
group by client_type;
select client_type, count(gender) as num_females
from clients
where gender = 'Female'
group by client_type;
The following SQL statements show the number of males by client type, then the number of females by client type. I would like an SQL statement to show the following columns: client_type, count(gender = 'Male'), count(gender = 'Female'). Is it possible to do this?
You could count a couple of case expressions:
SELECT client_type,
COUNT(CASE gender WHEN 'Male' THEN 1 END) AS num_males,
COUNT(CASE gender WHEN 'Female' THEN 1 END) AS num_females
FROM clients
GROUP BY client_type;

SQL / Postgresql count multiple columns with conditions

I have a simple table of the form:
id
gender
a_feature (bool)
b_feature (bool)
...
xyz_feature (bool)
and I want to sum over all feature columns dependent on gender.
metric
male
female
a_feature
345
3423
b_feature
65
143
...
...
...
xyz_feature
133
5536
Is there a simple way to do this, e.g. using the information_schema.
I found only the solution below, but this is very ugly:
select
'a_feature' as feature_name,
count(case a_feature and gender = 'male') as male,
count(case a_feature and gender = 'female') as female
from table
union
select
b_feature as feature_name,
count(case b_feature and gender = 'male') as male,
count(case b_feature and gender = 'female') as female
from table
.
.
.
select
xyz_feature as feature_name,
count(case xyz_feature and gender = 'male') as male,
count(case xyz_feature and gender = 'female') as female
from table
You can unpivot and aggregate. One method is:
select name,
sum(case when feature and gender = 'male' then 1 else 0 end) as num_male,
sum(case when feature and gender = 'female' then 1 else 0 end) as num_female
from ((select 'a_feature' as name, a_feature as feature, gender
from t
) union all
(select 'b_feature' as name, b_feature, gender
from t
) union all
. . .
) f
group by name;
In Postgres, you would unpivot using a lateral join:
select name,
sum(case when feature and gender = 'male' then 1 else 0 end) as num_male,
sum(case when feature and gender = 'female' then 1 else 0 end) as num_female
from t cross join lateral
(values ('a_feature', a_feature),
('b_feature', b_feature),
. . .
) v(name, feature)
group by name;
You can generate the list for values() using information_schema.columns if you are reluctant to type it all in.
EDIT:
You can construct the values clause using something like this:
select string_agg('(''' || column_name || ''', column_name)', ', ')
from information_schema.columns
where table_name = ?
When you use this in Postgres, what do you mean by t (I think t is for table) in "from t cross join lateral" and what do you mean by v in "v(name, feature)" ?
select name,
sum(case when feature and gender = 'male' then 1 else 0 end) as num_male,
sum(case when feature and gender = 'female' then 1 else 0 end) as num_female
from t cross join lateral
(values ('a_feature', a_feature),
('b_feature', b_feature),
. . .
) v(name, feature)
group by name;

Compare the count of data in same column in same table and display the larger value

I wanted to a count of the same field for different values for example:
user{user_id, gender}
Gender can have obviously male or female :)
i want to get count for all the males and females i.e.
COUNT(male) COUNT(female)
4 16
but i'm confused because they come from the same gender column thanks
ALSO, I Want the result to only display the higher count. Like
COUNT(female)
16
Try the following using case statement.
select
sum(case when gender = 'male' then 1 else 0 end) as total_male,
sum(case when gender = 'female' then 1 else 0 end) as total_female
from user
If you are using MySQL then use following
select
sum(gender = 'male') as total_male,
sum(gender = 'female') as total_female
from user
If you are using PostgreSQL then use filter
select
count(1) filter (where gender = 'male') as total_male,
count(1) filter (where gender = 'female') as total_female
from user
You can achieve your final result by following query. here is the demo.
select
case
when total_male < total_female then total_female
else total_male
end as total_count
from
(
select
count(1) filter (where gender = 'male') as total_male,
count(1) filter (where gender = 'female') as total_female
from users
) t

Assign a value when for integer when USE select query

This question is relevant to SQL Server. I have table with column called gender and 1 or 0 will be saved as integer. I want to know whether there is a method assign a label when I selecting it using SELECT statement.
For example
SELECT gender
FROM emp
AND if 1 occur Male AND 0 occur Female should be displayed.
Use the CASE operator, i.e. CASE gender when 1 then 'Male' else 'Female' end.
Full select as follows:
SELECT gender,
CASE gender
when 1 then 'Male'
else 'Female'
end as gender_name
FROM emp
UPD:
Option with N/A to process all possible optios (if gender field value not in range [0,1], but I prefer to use check constraint to determine possible values, to avoid weird/unexpected values):
SELECT gender,
CASE
gender
when 1 then 'Male'
when 0 then 'Female'
else 'N/A'
end as gender_name
FROM emp
You can use CASE:
SELECT CASE WHEN gender = 1 THEN 'Male' ELSE 'Female' END AS gender
FROM emp
You can use a CASE...WHEN...THEN...END for this
select case when GENDER = 1 then 'Male'
when GENDER = 0 then 'Female'
else 'N/A'
end as GENDER
from emp;
Find more about this here