Combine data and non data rows in SQL - 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';

Related

PostgreSQL - Query to list all students having atleast one mark different than 0

I'm working on PostgreSQL and I'm trying to retrieve the list of students having atleast one mark different than 0 in a specific matter or simply filter the students having 0's everywhere in a specific matter here's my DB structure:
Student {
id,
name,
other info..
}
Mark {
id,
student_id,
matter,
mark
}
for example
Student(1,"John"..)
Mark(1,1,'Mathematics',0);
Mark(2,1,'Mathematics',0);
Mark(3,1,'Mathematics',0);
Mark(4,1,'Physics',15);
Mark(5,1,'Physics',12);
Mark(6,1,'Physics',11);
Student(2,"Albert"..)
Mark(7,2,'Mathematics',0);
Mark(8,2,'Mathematics',17);
Mark(9,2,'Mathematics',0);
Mark(10,2,'Physics',0);
Mark(11,2,'Physics',0);
Mark(12,2,'Physics',0);
Student(3,"Chris"..)
Mark(13,3,'Mathematics',0);
Mark(14,3,'Mathematics',0);
Mark(15,3,'Mathematics',0);
Mark(16,3,'Physics',0);
Mark(17,3,'Physics',0);
Mark(18,3,'Physics',0);
In this case we filter John mathematic marks and Albert's Physics marks and we don't display Chris at all
You could try a basic join followed by filtering on records not having a zero mark:
SELECT DISTINCT s.id, s.name, m.matter
FROM Student s
INNER JOIN Mark m
ON m.student_id = s.id
WHERE m.mark <> 0;
You can do ti like this (result here)
select *
from student s,mark m
where s.id = m.student_id
and m.mark > 0
To find all students that have at least one non-zero mark, I would use an EXISTS condition:
select stu.*
from student stu
where exists (select *
from mark mrk
where mrk.student_id = stu.id
and mrk.mark <> 0);
Finding students that only have zero marks is a bit more tricky and requires aggregation.
select stu.*
from student stu
where exists (select mrk.student_id
from mark mrk
where mrk.student_id = stu.id
group by mrk.student_id
having bool_and(mrk.mark = 0));
Logically, the group by is not needed in the sub-query as it will only deal with a single student, but the SQL syntax rules require it.
This could also be expressed as a join against a derived table which might actually be a bit more efficient:
select stu.*
from student stu
join (
select mrk.student_id, bool_and(mrk.mark = 0) as all_marks_are_zero
from mark mrk
group by mrk.student_id
) m on m.student_id = stu.id and m.all_marks_are_zero
Online example

SQL query with more than 2 tables

I'm doing an exercise on ORACLE SQL.
Currently I got 3 tables.
Student values = "student_id ,name"
Subjects values = "subject_id, name"
Scores values = "score, student_id, subject_id"
I'm trying to retrieve the following information from my database.
Name of student, Name and id of the subject and finally the score that has the student_id "34560".
SELECT scores.score,
scores.subject_id,
student.name,
subject.subject_id,
subject.name
FROM scores
INNER JOIN students
ON scores.student_id = '34560'
INNER JOIN subject
ON /* and here's where i'm lost*/
Is there a way to put all together from the first part of the query where I call the list of students with student_id = "34560" and then query that list to see if it matches with the subject_id?
Use in operator for list of student id
SELECT sc.score, sc.subject_id,
st.name, sb.subject_id, sb.name
FROM scores sc
INNER JOIN students st
ON sc.student_id = st.student_id
INNER JOIN subject sb
ON sc.subject_id=sb.subject_id
where sc.student_id in ('34560','add_anotherstudentid','add_anotherstudentid') //you can add multiple student id

SQL query returns student id, course section id, and grade when section id 1000

Using Oracle Apex Browser, image of database
http://imgur.com/a/Hhblp#0
select s_ID, c_sec_ID, grade
from s_ID.ID, c_sec_ID.csID, grade.ID, grade.csID
where c_sec_ID = 1000
^ All I think of and I'm not sure if I'm suppose to join them together or group them either.
You have to join these tree tables COURSE_SECTION, ENROLLMENT and STUDENT to get desired output. Put INNER JOIN on three tables and add
Where Clause to filter records.
You can try this
SELECT S.s_ID, C.c_sec_ID, E.grade
FROM COURSE_SECTION C INNER JOIN ENROLLMENT E ON C.C_SEC_ID = E.C_SEC_ID
INNER JOIN STUDENT S ON S.S_ID = E.S_ID
WHERE C.C_SEC_ID = 1000

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' ;

SQL - Having 0 when using Count

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 ;