SQL - Having 0 when using Count - sql

I have a list of people that have their professions listed as the following:
Doctor Male
Teacher Male
Principal Male
Nurse Female
Doctor Male
When I group them by profession, I would like for Access to return 0 for any profession that is not in the sublist I have. Here is the code I am using:
SELECT Profession.Profession, Count(Profession.Profession) AS CountOfProfession
FROM People INNER JOIN Profession ON People.PeopleID = Profession.PeopleID
WHERE (((People.Sex)="Male"))
GROUP BY Profession.Profession;
I would like for it to yield 2 for Doctor since there are 2 males, but also yield 0 for Nurse since there are no male nurses. Please let me know how I can do this, thanks!

You need an outer join. I switched the order of the tables so it is a left join:
SELECT Profession.Profession,
sum(iif(people.sex = "Male", 1, 0)) AS CountOfProfession
FROM Profession LEFT JOIN
ON People.PeopleID = Profession.PeopleID
GROUP BY Profession.Profession;

This can be done with an outer join and moving the condition from the WHERE to the ON clause:
SELECT Profession.Profession,
COUNT(People.PeopleID) AS CountOfProfession
FROM Profession
LEFT JOIN People
ON ( People.PeopleID = Profession.PeopleID
AND People.Sex = 'Male' )
GROUP BY Profession.Profession ;

Related

Need Simple SQL direction

I'm trying to write a Ado SQL statement for my Access table and I'm getting the wrong results.
Employee Table
ID Name DriverID
1 Alex 1
2 Tom 2
3 Trevor 3
4 PHIL 0
5 Gina 4
Vehicle Table
ID PLATE EMPLOYEEID INSERVICE
1 123XYZ 1 N
2 456GFR 2 Y
3 TFV4FG 3 Y
4 F6GK7D 4 Y
5 GEY7GH 1 Y
I want result of All employes and to display the Vehcicle info if they are assigned to it.
Result should be
Name Plate
Alex GEY7GH
Tom 456GFR
Trevor TFV4FG
PHIL
Gina F6GK7D
SELECT Employee.ID, Employee.FirstName, Vehicles.Plate, Vehicles.InService
FROM Employee LEFT JOIN Vehicles ON Employee.ID = Vehicles.DriverID
WHERE (((Vehicles.InService)=True));
Does not display PHIL who is not assigned to a vehicle.
Just add the condition inside the join, making sure to use parentheses to avoid problems when joining with constants or anything but simple equals:
SELECT Employee.ID, Employee.FirstName, Vehicles.Plate, Vehicles.InService
FROM Employee LEFT JOIN Vehicles ON (Employee.ID = Vehicles.DriverID AND Vehicles.InService = True)
From the above tables, it looks like the DriverID Column in employee table aligns with the EmployeeID column in the vehicles table and the issue is the on clause in the join.
SELECT
Employee.ID
,Employee.FirstName
,Vehicles.Plate
,Vehicles.InService
FROM
Employee
LEFT JOIN Vehicles ON Employee.DRIVERID = Vehicles.EMPLOYEEID
WHERE
(((Vehicles.InService)=True));
Well, in a normal database, you would move the WHERE condition to the ON clause. But I don't think that MS Access supports this:
SELECT e.ID, e.FirstName, v.Plate, v.InService
FROM Employee as e LEFT JOIN
Vehicles as v
ON e.ID = v.DriverID AND v.InService = True;
An alternative is a subquery:
SELECT e.ID, e.FirstName, v.Plate, v.InService
FROM Employee as e LEFT JOIN
(SELECT v.*
FROM Vehicles as v
WHERE v.InService = True
) as v
ON e.ID = v.DriverID ;

SQL - Assess minimum value across multiple rows, then filter to show list of unique rows?

My end goal is to create a list of honor roll students. Each student has multiple rows, one for each grade. I want to say, look at their grades across these rows; only show 1 student name if none of their grades are <80%.
I've started just with this, but I'm stuck, I don't know how to assess across the multiple rows as a criterion for selecting a unique list.
SELECT students.first_name, students.last_name, storedgrades.storecode, storedgrades.percent,storedgrades.course_name
FROM storedgrades join
students
on students.ID = storedgrades.StudentID
where students.enroll_status=0 AND
storedgrades.termid>2799 AND
storedgrades.storecode = 'Q4'
Example of grades table:
BOB A 95
BOB D 65
ANDREA B 85
ANDREA A 95
EXAMPLE RESULT:
ANDREA
Use aggregation. I think this is what you want:
select s.id, s.first_name, s.last_name
from students s join
storedgrades sg
on s.ID = sg.StudentID
where s.enroll_status = 0 and
sg.termid > 2799 AND
sg.storecode = 'Q4'
group by s.id, s.first_name, s.last_name
having count(*) = 5 and -- you want all five courses
min(scorecode) >= 80;
Select a distinct list of student names, then compare with a NOT EXISTS to the grades table where the grade is less than 80%
SELECT distinct students.ID, students.first_name, students.last_name
FROM storedgrades s join
students
on students.ID = storedgrades.StudentID
where students.enroll_status=0 AND
storedgrades.termid>2799 AND
storedgrades.storecode = 'Q4' and not exists
(select 'x' from storedgrades s2 where s2.students.StudentID = s.StudentID and s2.first_name = s.first_name and
s.last_name = s2.last_name and s2.percent < 80)
EDIT: added in studentID to the join

Combine data and non data rows in SQL

Table : Mark M [Id, Subject, Mark]
Test Student Ids: 100, 101
Requirement: We need mark of both students of subject 'Maths'.
Condition: Student (101) was absent for Maths exam. So there wont be any record in Mark table for the student 101.
Expected Result:
Student ID Subject Mark
100 Maths 45
101 Maths 0
I.e. We need to add an additional row with Subject=Maths and Mark=0 for student 101
Thanks in advance
You can try using left join
select * from students a left join marks b
on a.studentid=b.studentid
you could use left join
select s.*, m.*
from student s
left join Mark m on m.Id = s.id
left join retrive row also if the values don't match
Assuming you have multiple subjects and are only interested in math, then you need to be careful about filtering:
select s.*, 'Maths' as subject, coalesce(m.mark, 0) as mark
from student s left join
mark m
on m.Id = s.id and m.subject = 'Maths';

Query with aggregating data from 2 tables

I have three tables in my Oracle db:
Peoples:
IdPerson PK
Name
Surname
Earnings:
IdEarning
IdPerson
EarningValue
Awards:
IdAward PK
IdPerson FK
AwardDescription
A person can have many earnings.
An earning can have many or no any earnings.
A person can have many awards, one award, or no any award.
I want to make a query that will return 3 columns:
Surname
SUM of all EarningValue of person with this surname
COUNT of all Awards for this person
An important thing is that i also need to display: 0 value if person don't have any award or earning. There is a possibility that person have an award but don't have any earning.
Is it possible to make such query?
SELECT p.IdPerson,
p.Surname,
NVL(SUM(e.EarningValue), 0) as SumEarnings,
COUNT(a.IdAward) as CntAwards
FROM Peoples p
LEFT JOIN Earnings e ON p.IdPerson = e.IdPerson
LEFT JOIN Awards a ON p.IdPerson = a.IdPerson
GROUP BY p.IdPerson,
p.Surname;
What returns this:
SELECT p.Surname,
(SELECT NVL(SUM(e.EarningValue), 0)
FROM Earnings e WHERE e.IdPerson = p.IdPerson) as SumEarnings,
(SELECT COUNT(aIdAward)
FROM Awards a WHERE a.IdPerson = p.IdPerson) as CntAwards
FROM Peoples p
yes of-course it is possible.
you just need to join the tables using multiple join queries and then apply sum() function to get sum of earnings and Count() to count the no. of awards.
Try the below query:
SELECT P.Surname,
Sum(E.EarningValue)AS Total_Earnings,
Count(A.IdAward) AS total_awards
FROM Peoples P
LEFT JOIN Earnings E
ON P.IdPerson = E.IdPerson
LEFT JOIN Awards A
ON A.IdPerson = P.IdPerson
GROUP BY P.IdPerson;
Yes it is possible, you just have to join the tables
SELECT Peoples.Surname, SUM(Earnings.EarningValue) as Earnings, COUNT(Awards. IdPerson) as Awards
FROM Peoples
INNER JOIN Earnings
ON Peoples.IdPerson = Earnings.IdPerson
INNER JOIN Awards
ON Peoples.IdPerson = Awards.IdPerson
GROUP BY Peoples.IdPerson;

SQL Query (or Join) for 3 tables

first time asking a question on Stack Overflow... Amazing resource, but there's just one thing that's really baffling me as a newcomer to SQL.
I have three tables and I would like to obtain the names of all the Mentors who are linked to Bob's students.
Table 1: TEACHERS
================
ID Name
================
1 Bob
Table 2: STUDENTS
===================================
STUDENT_ID Name TEACHER_ID
===================================
1 Jayne 1
2 Billy 5
3 Mark 2
Table 3: MENTOR_RELATIONSHIPS
==============================
ID STUDENT_ID MENTOR_ID
==============================
1 1 3
2 2 2
3 3 3
Table 4: MENTORS
=====================
MENTOR_ID Name
=====================
1 Sally
2 Gillian
3 Sean
I would like to run a query to find all of the mentors of Bob's students. So the mentors for all students with TEACHER_ID = 1
In this case Sean would be the result.
I know that it is something to do with Joins, or could I find this using a normal query??
Any help is much appreciated! Many thanks...
this should do the work
select distinct m.name from students s
inner join mentor_ralationships mr on mr.student_id=s.student_id
inner join mentors m on m.mentoir_id=mr.mentor_id
where s.teacher_id=1;
Without joins (not preferred)
SELECT mentors.name FROM mentors
WHERE mentors.id
IN (SELECT MENTOR_RELATIONSHIPS.mentor FROM MENTOR_RELATIONSHIPS
WHERE MENTOR_RELATIONSHIPS.student
IN (SELECT students.id FROM students WHERE students.teacher
= (SELECT teachers.id FROM teachers WHERE teachers.name = 'bob')));
It could be helpful for you as I had to retrieve data from three tables AssignedSubject, Section and SchoolClass when a teacher assigned to specific subject then I have to find out the his class and section details including subjectid which I did this way
select a.StaffID, a.SubjectID, s.ID as SectionId, s.Name as SectionName, S.Remarks as SectionRemarks, sc.ID as ClassId, sc.Name as ClassName, sc.Remarks as ClassRemarks from AssignedSubject a
inner join Section s on a.SectionId=s.ID
inner join SchoolClass sc on sc.ID=s.ClassId where a.StaffID=3068
You could try the following:
SELECT DISTINCT m.name
FROM students s INNER JOIN TEACHERS t ON t.ID = a.TEACHER_ID
INNER JOIN MENTOR_RELATIONSHIPS mr ON mr.Student_id = s.Student_id
INNER JOIN Mentors m ON mr.MENTOR_ID = s.MENTOR_ID
WHERE s.teacher_id = 1 WHERE t.Name = 'Bob';
SELECT TEACHER.NAME, STUDENTS.NAME AS STUDENT NAME, MENTORS.NAME AS MENTOR
FROM TEACHERS JOIN STUDENTS ON TEACHERS.ID = STUDENTS.TEACHER_ID
JOIN MENTOR_RELATIONSHIPS ON STUDENTS.STUDENT_ID =
MENTOR_RELATIONSHIPS.STUDENT_ID
JOIN MENTORS ON MENTOR_RELATIONSHIPS.MENTOR_ID = MENTORS.MENTOR_ID
WHERE TEACHER.NAME = 'Bob' ;