How to aggregate functions with groupby in SQL - sql

I have tables like this.
I would like to groupbyand aggregate this in diffrent aggregate functions.
product sex age
A M 10
B F 20
A F 30
C M 40
my desired result is like below.
Now I can group in productkey, but in this case, I must group them byproductandsex.
Are there any way to achieve it?
count(M) count(F) avarage(M) average(F)
A 1 1 10 30
B 0 1 NA 20
C 1 0 40 NA
Thanks

With conditional aggregation:
select product,
sum(case when sex = 'M' then 1 else 0 end),
sum(case when sex = 'F' then 1 else 0 end),
avg(case when sex = 'M' then age end),
avg(case when sex = 'F' then age end)
from tablename
group by product

You can simply use the PIVOT as follows:
select * from your_Table
pivot
(count(1) as cnt, avg(age) as average for sex in ('M','F'))

Related

Sqlite group by distinct count

I have table of customers operations:
date, client_id, gender
1 1 M
1 1 M
1 2 M
1 2 M
1 3 F
2 1 M
2 1 M
2 1 M
2 2 M
2 2 M
2 3 F
2 3 F
2 4 F
2 5 M
2 5 M
etc
Desired output is:
date, amount of males, (also need amount of females)
1 2 1
2 3 2
I need to group it by date, so i did it, then my goal is to find amount of each gender in each grouped group.
so i tried to do this to count amount of males:
sum(case when gender = 'M' then 1 else NULL end) as 'M%'
but its counted clients id 1 and 2 two times each, but i need to count it distinct.
On example above i expect this to return 2 because 2 male. But it return 4 because distinct construction doesnt work.
I tried this but it doesnt work and count '1' in result:
sum(distinct case when gender = 'M' then 1 else NULL end) as 'M%'
It's easier to count from the distinct rows of the table.
Also, use SQLite's feature to treat boolean expressions as 1 for true and 0 for false so you can sum them instead of using CASE expressions:
SELECT date,
SUM(gender = 'M') [amount of males],
SUM(gender = 'F') [amount of females]
FROM (SELECT DISTINCT date, client_id, gender FROM tablename)
GROUP BY date
See the demo.
You seem to want conditional count(distinct):
select date,
count(distinct case when gender = 'M' then client_id end) as count_m,
count(distinct case when gender = 'F' then client_id end) as count_f
from t
group by date;

How do I create a query in MS Access that finds and displays parents from the same table?

I have an MS Access table, which contains information about individuals within households. I need a way to link the adult record to the child record. These are literal parent/child records, but all held in a single table. The parent/child records share the Household_ID field. Assume at this stage that each household has 0,1 or 2 children and 1 or 2 adults. I can work on the more complex scenarios, just need to know where to start! Thanks for your help.
For example:
Person_ID Household_ID Age Gender
1 1 8 F
2 1 42 M
3 1 44 F
So for this household I'd like:
Household_ID Child_Age Child_Gender Adult_M_Age Adult_F_Age
1 8 F 42 44
You appear to want:
select t.*
from (select t.*,
max(case when gender = 'M' and age >= 18 then age end) over (partition by household_id) as adult_m_age,
max(case when gender = 'M' and age >= 18 then age end) over (partition by household_id) as adult_f_age
from t
) t
where age < 18;
EDIT:
In MS Access, you would phrase this differently. One method uses subqueries;
select t.*,
(select top 1 t2.age
from t as t2
where t2.household_id = t.household_id and
t2.gender = 'M' and
t2.age >= 18
) as adult_m_age,
(select top 1 t2.age
from t as t2
where t2.household_id = t.household_id and
t2.gender = 'F' and
t2.age >= 18
) as adult_f_age
from t
where age < 18;
Use conditional aggregation, apply your criteria to detect member's role. For example using Age-based criteria
select Household_ID,
max(case when Age < 18 then Age end) as Child_Age,
max(case when Age < 18 then Gender end) as Child_Gender,
max(case when Age >= 18 and Gender ='M' then Age end) as Adult_M_Age,
max(case when Age >= 18 and Gender ='F' then Age end) as Adult_F_Age
from tbl
group by Household_ID

How to have condition inside count SQL?

I already tried this code:
SELECT Count(Gender) As MaleCount, Count(Gender) As FemaleCount
FROM [Session4].[dbo].[Survey]
Where Gender = 'M' or Gender = 'F'
I can't get the accurate data when counting with two different conditions in one query.
Pictures below:
This is the result.
This is the original data
SELECT TOP (1000) [Departure]
,[Arrival]
,[Age]
,[Gender]
,[CabinType]
,[Q1]
,[Q2]
,[Q3]
,[Q4]
FROM [Session4].[DBO].[Survey]
count explain :
COUNT(*) counts all rows
COUNT(column) counts non-null value
COUNT(distinct column) counts distinct non-null value
COUNT(1) is the same as COUNT(*)
Use case/when + sum :
SELECT
sum(case when Gender = 'M' then 1 else 0 end ) As MaleCount,
sum(case when Gender = 'F' then 1 else 0 end ) As FemaleCount
FROM [Session4].[dbo].[Survey]
will produce somethings like this :
MaleCount | FemaleCount
1000 | 1255
Another way is using simple goup by
SELECT
Gender,
Count(*)
FROM [Session4].[dbo].[Survey]
GROUP BY
Gender
will produce :
Gender | Count
M | 1000
F | 1255
Try this out:
SELECT sum(case when Gender = 'M' then 1 else 0 end) As MaleCount,
sum(case when Gender = 'F' then 1 else 0 end) As FemaleCount
FROM [Session4].[dbo].[Survey]
Let me know in case of any doubts.

SQL query to transform combination of values into a column

I have a table like this:
user_id, gender, sent
1 M 100
1 F 120
2 M 20
2 F 30
I want a table like this from the above:
user_id, male_sent, female_sent, total_sent
1 100 120 220
2 20 30 50
I lack the (Postgres) SQL foo to figure this one out.
You can use an aggregate function with a CASE expression to get the result:
select user_id,
sum(case when gender = 'M' then sent else 0 end) male_sent,
sum(case when gender = 'F' then sent else 0 end) female_sent,
sum(sent) total_sent
from yourtable
group by user_id
See SQL Fiddle with Demo
What database are you using?
If you are using SQL Server, you could do something like this:
SELECT user_id,sum(case when gender = 'M' then sent else 0 end) as male_sent,
sum(case when gender = 'F' then sent else 0 end) as female_sent,
sum(sent) as total_sent
FROM your_table_name
GROUP BY user_id

AVG and Count from one columns

I Have a table by this Columns :
[Student_ID],[Class_ID],[Techer_ID],[Course_ID],[Marks]
and for range of marks exist name for example:
between 0 to 5 = D
between 6 to 10 = C
between 11 to 15 = B
between 16 to 20 = A
Now i need create T-Sq l Query for Return this result message columns:
Teacher_ID|Course_ID|Count(Marks)|Count(A)| Count(B)|Count(C)|Count(D)
Very thanks for your help
select Teacher_ID
, Course_ID
, count(*)
, sum(case when Marks between 16 and 20 then 1 end) as SumA
, sum(case when Marks between 11 and 15 then 1 end) as SumB
, sum(case when Marks between 6 and 10 then 1 end) as SumC
, sum(case when Marks between 0 and 5 then 1 end) as SumD
from YourTable
group by
Teacher_ID
, Course_ID
I would use the same approach as Andomar, only change sum to count like this:
select Teacher_ID
, Course_ID
, count(*)
, count(case when Marks between 16 and 20 then 1 end) as countA
, count(case when Marks between 11 and 15 then 1 end) as countB
, count(case when Marks between 6 and 10 then 1 end) as countC
, count(case when Marks between 0 and 5 then 1 end) as countD
from YourTable
group by
Teacher_ID
, Course_ID
In my opinion, the query looks more natural this way.
You can do this with PIVOT. (Note also that this formulation of the Marks-to-Letter calculation is a bit safer than one where both ends of each range must be typed.)
with T as (
select
Teacher_ID,
Course_ID,
case
when Marks <= 5 then 'countD'
when Marks <= 10 then 'countC'
when Marks <= 15 then 'countB'
else 'countA' end as Letter
from T
)
select
Teacher_ID,
Course_ID,
countD+countC+countB+countA as countMarks,
countA,
countB,
countC,
countD
from T pivot (
count(Letter) for Letter in ([countA],[countB],[countC],[countD])
) as P