SQL Group by on multiple conditions on same table - sql

enter image description hereI am trying to write an SQL query to get below output.
table has below data:
ID GENDER
10 M
10 F
10 F
20 F
20 M
Output:
ID Male Female
10 1 2
20 1 1
do i need to use case with group by. Can someone help here.

use simple group
select id,sum(case when GENDER = 'M' then 1 else 0 end) as Male,
sum(case when GENDER = 'F' then 1 else 0 end) as FeMale
from tablename
group by id

Related

Join column name to the value in another column

I have the following tables:
Category Table
> ID Code CodeValue Value
> 1 sex 1 Male
> 1 sex 2 Female
> 2 age 1 Under 20
> 2 age 2 Between 20 and 40
> 2 age 3 Over 40
Data Table
> sex age
> 1 1
> 1 2
> 2 2
> 1 3
I want to return the Value of a field based on the Code, so that the final table would like something like below:
> sex age
> Male Under 20
> Male Between 20 and 40
> Female Between 20 and 40
> Male Over 40
Is there any way to join the values (sex age) of the 'Code' column in the Category Table with the column names in the Data table, and then return the corresponding 'Value' (Male, Female, Under 20 etc...)
Thanks!
Sam
You can join the table twice, once for each category.
SELECT cts.value sex, cta.value age
FROM data_table dt
INNER JOIN category_table cts
ON dt.sex = cts.code_value AND cts.code = 'sex'
INNER JOIN category_table cta
ON dt.age = cta.code_value AND cta.code = 'age'

SQL Aggregation prior to advanced SQL

Given a simple case like this:
Gender DeptID
--------------
M 1
F 1
M 2
F 2
F 2
What SQL statement I need to write If I want to generate the following result using SQL without using advanced CUBE, Rollup, etc., just using plain SQL-92:
GenderSum Dept1Sum Dept2Sum
----------------------------
M 1 1
F 1 2
I was wondering how such information would be generated by ETL in the past using SQL?
Remark: It is possible to use Group by on gender and union that with a group by on DetptId to get a vertical result set but this is clearly not what I want.
You can try the following pivot query:
SELECT Gender AS GenderSum,
SUM(CASE WHEN DeptID = 1 THEN 1 ELSE 0 END) AS Dept1Sum,
SUM(CASE WHEN DeptID = 2 THEN 1 ELSE 0 END) AS Dept2Sum
FROM yourTable
GROUP BY Gender

Sort by aggregate value in sql

Let's say I have the following student data:
classroom gender student_id
-------------------------------------
First Grade M 123
First Grade F 124
First Grade F 125
Second Grade M 126
Third Grade M 127
...
I want to produce the following result: top 3 biggest classrooms ordered by total number of students with detail for each:
classroom boys_count girls_count total_count
--------------------------------------------------
Third Grade 30 30 60
First Grade 20 5 25
Fourth Grade 10 10 20
How can I do that in sql ? If necessary, I can use specific postrges features.
What I tried so far:
SELECT count(*) as total_count
, gender
, classroom
ORDER BY 1
GROUP BY classroom, gender
LIMIT 3
Then I re-organise results in some scripting language. But this is too slow. I want to have the correct results with one query
select classroom as name,
sum(case when gender = 'M' then 1 else 0 end) as boys_count,
sum(case when gender = 'F' then 1 else 0 end) as girls_count,
count(*) as total_count
from your_table
group by classroom
order by count(*) desc
limit 3

Creating a SQL View where columns are data from another column

I am developping a simple criminal records management system using SQL Server.
I have the following tables:
Criminal (
CriminalID,
Gender ...)
Victim (
VictimID,
Gender ...)
Crime(
CrimeID,
CriminalID,
VictimID ...)
I am interested in creating a view that gives us a simple statistic about Gender of victims by gender of criminals.
Example of wanted output:
Victim \ Criminal | Male | Female
Male | 4 | 2
Female | 8 | 5
Grouping the Number of crimes only by gender of victims or only by gender of criminals isnt hard , But how can i perform this task ? How to Expand the Gender of criminals into 2 separate columns and perform the needed task ?
You need a conditional sum:
select criminal.gender
,SUM(case when victim.gender = 'M' then 1 else 0 end) as "Male"
,SUM(case when victim.gender = 'F' then 1 else 0 end) as "Female"
from ...
group by criminal.gender
The CASE returns either 1 or 0...

Aggregation two table

I have two tables
nameTB contains:
id | name | gender | nationalityid
nationalityTB contains:
nationalityid | nationalityname
I want create sql query to return the result:
nationalityname female male total
UK 10 5 15
USA 11 7 18
You should be able to easily get the result by joining the tables and using an aggregate function with conditional logic (like a CASE expression):
select nt.nationalityname,
sum(case when nm.gender = 'Female' then 1 else 0 end) Female,
sum(case when nm.gender = 'Male' then 1 else 0 end) Male,
count(*) Total
from nationalityTB nt
left join nameTB nm
on nt.nationalityid = nm.nationalityid
group by nt.nationalityname;
See SQL Fiddle with Demo