Getting data from unrelated tables - sql

I've got this homework for database 'SCHOOL'
Table Student (StudentID, Name, Surname, etc..)\
Table Application (ApplicationID, StudentID, ClassID)\
Table Class (ClassID, ClassName, TeacherID)\
Table Teacher (TeacherID, Name, Surname, etc..)
There are some other tables and columns in the database but I don't think they're important to this query.
I need to get name of the teachers for whose classes no student signed up. Let's say there is no one signed up for Math class, and I need to get the name of the teacher for that Math class.
SELECT Teacher.Name, Teacher.Surname, Class.ClassName
FROM Teacher
INNER JOIN Class ON Class.TeacherID = Teacher.TeacherID
INNER JOIN Application ON Application.ClassID = Class.ClassID
INNER JOIN Student ON Student.StudentID = Application.StudentID
WHERE Application.PredmetID IS NULL
Help would be appreciated.

I would recommend NOT EXISTS:
select t.name
from class c join
teacher t
on t.teacherid = c.teacherid
where not exists (select 1
from application a
where a.classid = c.classid
);

I need to get name of the teachers for whose classes no student signed up
Select T.name
From Teacher T inner join [Class] C on T.TeacherId = C.TeacherId
Where C.ClassId not in (Select Distinct ClassId from Application)

Related

Find missing records in ONE-TO-MANY relationship query

I have 3 tables:
Class
Id
ClassName
guid
1A
guid
2A
Subject
Id
SubjectName
guid
Math
guid
Biography
SubjectOfEachClass
Id
ClassId
SubjectId
TeacherName
guid
guid
guid
James Bond
The way I wanted these tables to work is:
There will be 10 classes in table Class.
There will be 10 subjects in table Subject.
Each class will has 10 subjects and for 10 classes there will be 100 records.
I ran into some problems, I queried the SubjectOfEachClass table and there are only 95 records.
The query command I use to find the missing subjects is:
SELECT *
FROM Subject s
JOIN (
SELECT *
FROM SubjectOfEachClass
WHERE ClassId = 'guid'
) AS sc ON s.Id = sc.SubjectId
I replaced the ClassId several times until I found the class that misses some of the subjects.
I reckon this way of querying is not efficient at all. If I have 100 subjects and 100 classes, there will no chance that I will find the missing subjects.
to find every missing subject in all classes:
select c.id, c.classname , s.id , s.SubjectName
from class c
cross apply Subject s
where not exists (
select 1 from SubjectOfEachClass sc
where sc.classid = c.id and sc.subjectid = s.id
)
Try this:
SELECT c.id AS classId,
count(sc.id) AS countOfSubjects
FROM SubjectOfEachClass AS sc
INNER JOIN Classes AS c ON c.id = sc.classId
GROUP BY c.id
ORDER BY countOfSubjects
The abnormal values will be floated.
Your primary table should be SubjectOfEachClass, then those foreign tables Subject and Class will join your primary table.
select *
from SubjectOfEachClass sc
inner join Subject s on s.guid=sc.guid
inner join Class c on c.guid=sc.guid
where sc.ClassId = 'guid'

Linking of field data to field name between two tables

I have one table name Class_sub where I have subjects name according to the classes, I have weekly_test table where the same subject's marks have to be entered.
My problem is to show subject name as field name in weekly_test table reference to class_sub table data fields.
If you have the following tables:
CLASS
id
name
SUBJECT
id
name
CLASS_SUBJECT
id
class_id
subject_id
WEEKLY_MARKS
id
class_subject_id
test_date
mark
The following query will work:
SELECT s.name as subject_name,
c.name as class_name,
wm.test_date,
wm.mark
FROM weekly_marks wm
INNER JOIN class_subject cs ON wm.class_subject_id = cs.id
INNER JOIN class c ON cs.class_id = c.id
INNER JOIN subject s ON cs.subject_id = s.id
A bit of a guess here, but assuming the class_subject table you're talking about is joining of subjects (students?) to the classes they are enrolled in.

sql - combining columns from different tables

I have four different tables
class(classID, className)
person(personID, name)
schedule(personID, classID)
enrollment(personID, grade)
What is the easiest way to get each distinct column in one table?
I understand that I would start with enrollment, get the personID and grade, add them to the result table, then use the personID to get the name as well as the classID, and then use the classID to get the className. I just don't know exactly how to do that.
It seems that you need something like this:
SELECT p.name personName, e.grade, c.className
FROM person p
JOIN enrollment e ON e.personId = p.personId
JOIN schedule s ON s.personId = p.personId
JOIN class c ON c.classId = s.classId
WHERE p.personId = 1;

Multiple joins onto same table

i have the following tables:
TABLE: teachers:
teacherID
teacherName
TABLE: students:
studentID
studentName
teacherID
advisorID
so, usually, i know i can get a single row per student, with their teachers name using an INNER JOIN.
but in this case - the advisor and tacher - are from the same teachers table. so how can i join onto the teachers table twice - once getting the teacher name, and then again to get the advisor name?
hope this is clear
thanks!
This lists students with the names of their teachers and advisors if any, in alpha order of student, without either (a) the teacher or (b) the advisor having to exist. If you want only where those names exist, change the respective join to an INNER join.
SELECT s.studentname as [Student], t.teachername as [Teacher], a.teachername as [Advisor]
FROM Students s
LEFT JOIN Teachers t ON s.TeacherID = t.TeacherID
LEFT JOIN Teachers a ON s.AdvisorID = a.TeacherID
ORDER BY 1, 2
You can join to the same table more than once, just give it a different alias for each join, and name your fields in a descriptive enough way. Use a left join if there might not be a link, but if a student always has both a teacher and an advisor, a straight join should be fine.
Something like this:
select s.studentname student
, t.teachername teacher
, a.teachername advisor
from students s
join teacher t
on t.teacherID = s.teacherID
join teacher a
on a.teacherID = s.teacherID
Why not try something like the following. Its been a while since I've done SQL so this may not work.
SELECT s.studentName AS Student, t.teacherName AS Teacher, a.teacherName AS Advisor
FROM teachers t, teachers a, students s
WHERE t.teacherID = s.teacherID AND a.teacherID = s.advisorID

SQL to select a table through a generic relationship

In a relational database I have three tables. Using SQL Server.
person(id, type)
student(id, person_id, type, student specific fields)
teacher(id, person_id, type, teacher specific fields)
Student and teacher are both people, therefore a student will have a record in both the person and student tables, as will the teacher. Student and teacher have foreign keys to person. Student and teacher have different field definitions therefore a union will NOT work.
Now I have the person's id and depending on whether the person is a student or teacher I would like to select * from the relevant table (not person).
For example, if the person is a student I would like my query to select the student table.
I can think of a few inefficient methods but I am looking for the optimum one.
I would suggest a UNION
SELECT student.*
FROM student
WHERE person_id= #id
UNION
SELECT teacher.*
FROM teacher
WHERE person_id= #id
if exists(select person_id from student where person_id = #id)
select * from student where person_id = #id
else
if exists(select person_id from teacher where person_id = #id)
select * from teacher where person_id = #id
If your RDBMS is SQLServer, then I would abstract a view along the lines of podiluska's union, mapping out specific fields in Student and Teacher to common names, and padding with NULLs where no mapping is possible
And assuming that Students and Teachers inherit from person (i.e. both are 0..1 to 1 with Person), then they can share the same primary key, i.e. no need for new surrogates keys on Teacher and Student.
I've assumed that person.type determines whether the person is a Student(S) or Teacher(T).
CREATE VIEW SubClassesOfPerson AS
SELECT p.id as PersonId,
p.name as PersonName,
p.OtherBaseFieldsHere,
s.SomeStudentSpecificField AS MappedField1,
s.SomeStudentSpecificFieldX AS MappedFieldX,
s.SomeStudentSpecificField as MappedFieldForStudentOnly,
NULL as MappedFieldForTeacherOnly -- Pad this because it can't be mapped
FROM person p
INNER JOIN student s
on s.person_id = p.id AND p.type = 'S'
UNION
SELECT p.id as PersonId,
p.name as PersonName,
p.OtherBaseFieldsHere,
t.SomeTeacherSpecificField AS MappedField1,
t.SomeTeacherSpecificFieldX AS MappedFieldX,
NULL as MappedFieldForStudentOnly, -- Pad this because it can't be mapped
t.SomeTeacherSpecificField as MappedFieldForTeacherOnly
FROM person p
INNER JOIN teacher t
on t.person_id = p.id AND p.type = 'T'