SQL Aggregation prior to advanced SQL - 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

Related

Is there a way to count the number of values in column?

I am a newbie studying MSSQL and Database.
I am trying to write a SQL query to count values in the column.
Following table is original one.
name value
----------
A 1
A 1
A 2
B 1
B 2
I want to get a table like this.
name one two
--------------
A 2 1
B 1 1
A has two 1 and one 2 and B has one 1 and 2. It seems I can accomplish it using COUNT built-in function. I tried but failed. Is there any idea to do it?
use conditional aggregation
select name, sum(case when value=1 then 1 else 0 end) as one,
sum(case when value=2 then 1 else 0 end) as two
from table_name group by name

SQL Group by on multiple conditions on same table

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

Pivot not returning aggregate (SQL Adventureworks)

I am using the Adventureworks sample database (HumanResources.Employee table is the database).
For simplicity I will take a sample of the table:
HireDate Gender SalariedFlag
-----------------------------------------
2014-01-01 M 1
2015-01-30 F 1
2014-01-30 M 1
2014-02-12 F 0
2014-03-11 F 1 and so on
Code:
SELECT
YEAR(hiredate), F, M
FROM
HumanResources.employee
PIVOT
(sum(SalariedFlag)
FOR gender IN ([F], [M])
) AS gg
-- Unable to use sum though since its bit field
Expected output:
Year F M
-------------------
2014 1 2 # count(SalariedFlag)
2015 1 0 # count(SalariedFlag)
But I really get:
No name F M
-------------------------------
2014 0 1
2015 1 0
2014 0 1
2014 1 0
2014 1 0
and so on.
So basically in output its not considering the salariedflag column at all, it is simply returning 1 in F if the person was female and 1 in M if person was male.
What am I doing wrong?
Firstly, counting the value of SalariedFlag isn't going to achieve anything. COUNT counts the number of rows with a non-NULL value, and all your rows have a non-NULL value. Instead you want to COUNT the number of rows where the value of SalariedFlag is 1.
You might, therefore, be able to SUM the column, however, as it's a "flag" it's more likely to be a bit and you can't SUM a bit. Therefore using COUNT and checking the value is 1 with a CASE would likely be better.
Personally, rather than using the restrictive PIVOT operator, I would suggest you use conditional aggregation. This gives you the following:
SELECT YEAR(HireDate) AS HireYear,
COUNT(CASE WHEN Gender = 'M' AND SalariedFlag = 1 THEN 1 END) AS M,
COUNT(CASE WHEN Gender = 'F' AND SalariedFlag = 1 THEN 1 END) AS F
FROM #YourTable
GROUP BY YEAR(HireDate);
db<>fiddle

Presto SQL pivoting (for lack of a better word) data

I am working with some course data in a Presto database. The data in the table looks like:
student_id period score completed
1 2016_Q1 3 Y
1 2016_Q3 4 Y
3 2017_Q1 4 Y
4 2018_Q1 2 N
I would like to format the data so that it looks like:
student_id 2018_Q1_score 2018_Q1_completed 2017_Q3_score
1 0 N 5
3 4 Y 4
4 2 N 2
I know that I could do this by joining to the table for each time period, but I wanted to ask here to see if any gurus had a recommendation for a more scalable solution (e.g. perhaps not having to manually create a new join for each period). Any suggestions?
You can just use conditional aggregation:
select student_id,
max(case when period = '2018_Q1' then score else 0 end) as score_2018q1,
max(case when period = '2018_Q1' then completed then 'N' end) as completed_2018q1,
max(case when period = '2017_Q3' then score else 0 end) as score_2017q3
from t
group by student_id

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