Total of Multiple COUNT SELECTS from the multiple tables not working - sql

I have A attendance report in which I want to show report day wise like this :
I can calculate Sum individually , But not the total of all Sum
My StudentAttendance Table :
ID ClassID SubjectID Day10 Day11 Day12 Day13 Day14 Day15 ProfessorID
215 23 46 P 36 36
216 23 47 P 36
217 23 48 P 36 P 36
218 17 35 P 28
I have Tried this Query :
select ClassID,
sum(case when Day14= 'P' then 1 else 0 end) Present,
sum(case when Day14= 'A' then 1 else 0 end) Absent,
sum(case when Day14= 'L' then 1 else 0 end) Leave
from studentattendance
group by ClassID,Day14
I tried Sum(Present.Absent,Leave)..But not working What I am missing ??

There is no SQL syntax for a SELECT with multiple FROM clauses(WITHOUT nesting).
Perhaps you want something like this?
select
classID,
count(Day14) Total,
sum(case when Day14='P' then 1 else 0 end) Present,
sum(case when Day14='A' then 1 else 0 end) Absent,
sum(case when Day14='L' then 1 else 0 end) Leave
from studentattendance
group by classID
Here Total is merely the total number of records in each classID. The sum(case..when..) statements simulates a selective count() only when certain condition is satisfied (Day14 is either Present,Absent or Leave). Note that there is no guarantee that the Total to be equal to Present+Absent+Leave if you expect values other than these 3 to be present in the column Day14

Related

How do I query a table in SQL to produce a result where column names are stacked vertically based on a condition?

Suppose I have a SQL table titled Users with the following example data:
Description Days
--------------------------
Healthy 10
High-blood pressure 20
Cholesterol 23
Diabetes 31
High-blood pressure 8
Healthy 12
Diabetes 18
Cholesterol 25
High-blood pressure 20
Healthy 6
How would I produce a result that looks like the following where the columns: Less_than_20_days, 20_days and Greater_than_20_days contains counts from the table above
Description Less_than_20_days 20_days Greater_than_20_days
-----------------------------------------------------------------------------------
Healthy 3 0 0
High-blood pressure 1 2 0
Cholesterol 0 0 2
Diabetes 1 0 1
I'm trying to get this to work in SQL Server and have tried using the union operator, temp tables and ctes but I can't seem to get the desired result.
Any help would be much appreciated!
You can combine case with sum():
select
[Description]
,sum(case when [Days] < 20 then 1 else 0 end) as Less_than_20_days
,sum(case when [Days] = 20 then 1 else 0 end) as d20_days
,sum(case when [Days] > 20 then 1 else 0 end) as Greater_than_20_days
from users
group by [Description]
Use conditional aggregation:
select description,
sum(case when days < 20 then 1 else 0 end) as num_lt_20,
sum(case when days = 20 then 1 else 0 end) as num_eq_20,
sum(case when days > 20 then 1 else 0 end) as num_gt_20
from t
group by description

SQL: PIVOT with join

Newbie question:
I have table below
Period Customer Balance
40 1 10
40 2 15
39 1 9
38 1 10
38 2 20
I would like to order it so that I have one column for each period,
Customer BalancePeriod38 BalancePeriod39 BalancePeriod40
1 10 9 10
2 15 . 20
Is this possible?
You can pivot the data using aggregation with case:
select customer,
sum(case when period = 38 then balance else 0 end) as balance_period_38,
sum(case when period = 39 then balance else 0 end) as balance_period_39,
sum(case when period = 40 then balance else 0 end) as balance_period_40
from your_table
group by customer;

Getting sub-counts along with Average and Count

I have two tables...
MODULES ENROLMENTS
GroupNo StudentNo
Title GroupNo
Tutor CourseworkMark
DayNo ExamMark
Time
Room
Semester
I wish to create a view that displays the average mark achieved in coursework and exam for each module and also a count of the number of students who achieved >70, 60-69, 50-59, 40-49 and <40. Is this possible?
I have the average marks worked out with...
SELECT Title,
AVG(CourseworkMark) AS AverageCoursework,
AVG(ExamMark) AS AverageExam
FROM tblModules INNER JOIN tblEnrolments
ON tblModules.GroupNo = tblEnrolments.GroupNo
GROUP BY Title;
You can use a SUMmed CASE expression to do this;
SELECT Title,
AVG(CourseworkMark) AS AverageCoursework,
AVG(ExamMark) AS AverageExam,
SUM(CASE WHEN CourseworkMark > 70 THEN 1 ELSE 0 END) AS CourseworkMarkOver70,
SUM(CASE WHEN CourseworkMark BETWEEN 60 AND 70 THEN 1 ELSE 0 END) AS CourseworkMarkOver60To69,
SUM(CASE WHEN CourseworkMark BETWEEN 50 and 59 THEN 1 ELSE 0 END) AS CourseworkMarkOver50To59,
SUM(CASE WHEN CourseworkMark BETWEEN 40 and 49 THEN 1 ELSE 0 END) AS CourseworkMarkOver40To49,
SUM(CASE WHEN CourseworkMark < 40 THEN 1 ELSE 0 END) AS CourseworkMarkUnder40
FROM tblModules INNER JOIN tblEnrolments
ON tblModules.GroupNo = tblEnrolments.GroupNo
GROUP BY Title;

Use of AVG function to determine percentages in a SQL query

I want to know what percentage of records have a given value, where percentage is defined as the number of records that match the value divided by the total number of records. i.e. if there are 100 records, of which 10 have a null value for student_id and 20 have a value of 999999, then the percentage_999999 should be 20%. Can I use the AVG function to determine this?
Option 1:
SELECT year, college_name,
sum(case when student_id IN ('999999999') then 1 else 0 end) as count_id_999999999,
count_id_999999999/total_id as percent_id_999999999,
sum(case when student_id IS NULL then 1 else 0 end) as count_id_NULL,
count_id_NULL/total_id as percent_id_NULL
count(*) as total_id
FROM enrolment_data ed
GROUP BY year, college_name
ORDER BY year, college_name;
Option 2:
SELECT year, college_name,
sum(case when student_id IN ('999999999') then 1 else 0 end) as count_id_999999999,
avg(case when student_id IN ('999999999') then 1.0 else 0 end) as percent_id_999999999,
sum(case when student_id IS NULL then 1 else 0 end) as count_id_NULL,
avg(case when student_id IS NULL then 1.0 else 0 end) as percent_id_NULL
count(*) as total_id
FROM enrolment_data ed
GROUP BY year, college_name
ORDER BY year, college_name;
I created a similar table with 100 records, 20 999999999s, 10 nulls, and 70 1s. This worked for me on SQL Server:
select count(*), StudentID
from ScratchTbl
group by StudentID;
(No column name) StudentID
10 NULL
70 1
20 999999999
select avg(case when StudentID = '999999999' then 1.0 else 0.0 end) as 'pct_9s',
sum(case when StudentID = '999999999' then 1 else 0 end) as 'count_9s',
avg(case when StudentID is null then 1.0 else 0.0 end) as 'pct_null',
sum(case when StudentID is null then 1 else 0 end) as 'count_null'
from ScratchTbl
pct_9s count_9s pct_null count_null
0.200000 20 0.100000 10
I have a feeling that your use of the group by clause could be creating problems for you, perhaps select a specific year/college using the where clause (and get rid of the group by line) and see if you get the results you expect.

How to display the total number of passed and failed students batch wise

I have a table tbl_marksObtained that contains the following data:
stdID sub marks_Obtained
201bct2007 computer 45
201bct2007 Drawing 0
202bct2007 computer 0
203bct2007 Drawing 65
.
230bct2007 computer 77
301bct2008 physics 0
301bct2008 computer 55
.
.
401bct2009 and so on..
Now I would like to display the results as:
year sub pass fail
2007 computer 20 10
2007 Drawing 15 15
2008 computer 28 2
2009 computer 20 10
I obtained the pass fail of particular year and subject by following code:
SELECT
SUM( CASE WHEN marks_obtained > '0' THEN 1 END) AS pass,
SUM( CASE WHEN marks_obtained = '0' THEN 1 END) AS fail
FROM
tblstudentexammarks
WHERE
sub ='computer' AND stdID LIKE '%bce2007'
but how will I get the above results year wise data
select
RIGHT(stdID,4) as year,
sub,
sum(CASE WHEN marks_Obtained>0 then 1 else 0 end) as pass,
sum(CASE WHEN marks_Obtained=0 then 1 else 0 end) as fail
from tblstudentexammarks
group by RIGHT(stdID,4),sub
order by 1
try this:
select stdID [Year],sub,
sum(case when PF='P' then 1 else 0 end) as Pass,
sum(case when PF='F' then 1 else 0 end) as Fail
from(
select RIGHT(stdID,4) stdID,sub,
case when marks_Obtained=0 then 'F' else 'P' end PF
from mark_sheet)a
WHERE
sub ='computer' AND stdID LIKE '%bce2007'
group by stdID,sub