Reputation: 3
We have two student tables with details in one table and marks in another, we need to calculate the percentage of marks obtained by students and divide them according to percentage and gender. Attached image for further understanding. image
Adding my trial_code:
create table student_details (id int primary key, student_name varchar(20), student_gender varchar(15))
insert into student_details values(1,'test','Male'),(2,'test2','Female')
select * from student_details
create table student_marks(id int primary key, student_id int foreign key references student_details(id)
,[subject] varchar(20)
,marks int)
insert into student_marks values(1,1,'English',25),(2,2,'English',65)
,(3,1,'Social',25),(4,2,'Social',65)
,(5,1,'Bio',25),(6,2,'Bio',65)
,(7,1,'Maths',25),(8,2,'Maths',65)
,(9,1,'Science',25),(10,2,'Science',65)
select avg(marks) from student_marks
group by student_id
select sum(marks) from student_marks
group by id
create or alter proc student_avg_marks
as
begin
declare @column varchar(50)
select case when avg(sm.marks)<25 then 'Below 25%'
when (avg(sm.marks)between 25 and 50) then '25% - 50%'
when (avg(sm.marks)between 50 and 75) then '50% - 75%'
when avg(sm.marks)<25 then 'Above 75%'end as avg_marks,
count(student_id) as [total no. of students],
sum(case when sd.student_gender='Male' then 1 else 0 end),
sum(case when sd.student_gender='Female' then 1 else 0 end)
from student_details as sd inner join
student_marks as sm on sd.id=sm.student_id
group by sm.student_id
end
exec student_avg_marks
The output should be something like in the image, even if no records are present the avg_marks column should display all records in it.
Fiddle The final output should count no. of students but the result displayed is no. of subjects.
If no of students is 3 and 2 are male and 1 is female then it should represent that and 50 lies in '50 to 75' range.
Upvotes: 0
Views: 101
Reputation: 2615
hello please test this:
CREATE OR ALTER PROC student_avg_marks
AS
BEGIN
--declare @column varchar(50)
SELECT V.avg_marks ,isnull(T2.[total no. of students],'') as [No. of Students], isnull(T2.male,'') as Male, isnull(T2.female,'') as Female
FROM (values('Below 25%') ,('25% - 50%') ,('50% - 75%'),('Above 75%')) V (avg_marks)
LEFT JOIN (
select case when avg(sm.marks) < 25 then 'Below 25%'
when avg(sm.marks) between 25 and 50 then '25% - 50%'
when avg(sm.marks) between 50 and 75 then '50% - 75%'
when avg(sm.marks) > 75 then 'Above 75%'end as avg_marks,
COUNT(DISTINCT sm.student_id) as [total no. of students],
SUM(case when sd.student_gender='Male' then 1 else 0 end) AS male,
SUM(case when sd.student_gender='Female' then 1 else 0 end) AS female
from student_details as sd inner join
student_marks as sm on sd.id=sm.student_id
group by sd.student_gender) AS T2 ON V.avg_marks = T2.avg_marks
GROUP BY V.avg_marks, T2.[total no. of students], T2.male, T2.female
END
if we execute the query:
GO
EXECUTE student_avg_marks
Upvotes: 1
Reputation: 382
Use a select with your desired values
create or alter proc student_avg_marks
as
begin
declare @column varchar(50)
SELECT V.avg_marks ,T2.[total no. of students] ,T2.male ,T2.female FROM (values('Below 25%') ,('25% - 50%') ,('50% - 75%'),('Above 75%')) V (avg_marks)
LEFT JOIN (
select case when avg(sm.marks)<25 then 'Below 25%'
when (avg(sm.marks)between 25 and 50) then '25% - 50%'
when (avg(sm.marks)between 50 and 75) then '50% - 75%'
when avg(sm.marks)<25 then 'Above 75%'end as avg_marks,
1 as [total no. of students],
case when sd.student_gender='Male' then 1 else 0 end AS male,
case when sd.student_gender='Female' then 1 else 0 end AS female
from student_details as sd inner join
student_marks as sm on sd.id=sm.student_id
group by sm.student_id ,sd.student_gender) AS T2 ON V.avg_marks = T2.avg_marks
end
Upvotes: 0