Sql select clause with three table - sql

I am trying to write a sql query to show student list for each course.
The diagram below show the database relationship.
The SQL query I have written is:
select * from Courses
inner join Enrollments on Enrollments.CourseId = Courses.CourseId
inner join Student on Enrollments.StudentId = StudentId
where Courses.CourseId = 1
The issue is that i am getting returned alot more data than I expected as only one student is registered for the course but i get ten entries. I am not sure if i have done somethings fundamental wrong or is my query the issue.
This is the data
This is the result
I expected only two rows to be returned.
Thanks

Every column in your query must be qualified with the table's name.
You did not qualify the column StudentId in this join:
inner join Student on Enrollments.StudentId = StudentId
If you did you would find the error which is that there is no column StudentId in the table Student and you should use the column Id:
select * from Courses
inner join Enrollments on Enrollments.CourseId = Courses.CourseId
inner join Student on Enrollments.StudentId = Student.Id
where Courses.CourseId = 1
or better with aliases for the tables:
select *
from Courses as c
inner join Enrollments as e on e.CourseId = c.CourseId
inner join Student as s on e.StudentId = s.Id
where c.CourseId = 1

The primary key of table Student is Id, not StudentId.
So the correct query is:
select * from Courses
inner join Enrollments on Enrollments.CourseId = Courses.CourseId
inner join Student on Enrollments.StudentId = Student.Id
where Courses.CourseId = 1

Related

Write a query to display the student names and the maximum mark scored by them in any subject

I have tried using group by and getting an error message of single row function cannot return multiple values.
It has three tables to be selected student, subject and mark.
If you only required student_id and MAX number, you can use only tables Student and Marks as below-
SELECT A.stident_id,MAX(B.Value) max_marks
FROM Student A
INNER JOIN Mark B ON A.Student_id = B.Student_id
GROUP BY A.stident_id
But if you need subject name as well, you can try this below logic-
SELECT AA.stident_id,AA.stident_name,
D.Subject_name,AA.max_marks
FROM
(
SELECT A.stident_id,A.stident_name,MAX(B.Value) max_marks
FROM Student A
INNER JOIN Mark B ON A.Student_id = B.Student_id
GROUP BY A.stident_id
)AA
INNER JOIN Marks C ON AA.stident_id = C.stident_id
AND AA.max_marks = C.Value
INNER JOIN Subject D ON C.subject_id = D.subject_id

How to make a query from 4 tables

I am having a problem creating a View using SQL. I need to make a View of 4 tables:
tbl_school, tbl_teacher, tb_student, and tbl_class.
This is my table structure:
And this is my View Statement
SELECT
tbl_school.school_id,
tbl_school.school_nm,
(SELECT COUNT(*) FROM tbl_class) AS class,
(SELECT COUNT(*) FROM tbl_teacher) AS teacher,
(SELECT COUNT(*) FROM tbl_student) AS student
FROM
tbl_school
INNER JOIN tbl_teacher ON tbl_school.school_id = tbl_teacher.school_id
INNER JOIN tbl_class ON tbl_teacher.teacher_id = tbl_class.teacher_id AND tbl_school.school_id = tbl_class.school_id
INNER JOIN tbl_student ON tbl_class.class_id = tbl_student.class_id
GROUP BY
tbl_school.school_id
And this is the query result:
The problem is that I have one teacher in SD1 School and another teacher in SD2 School. Each teacher has one class and SD1 School has two students and SD2 School has one student.
Is there a way I can get the results that I desire?
You can use an aggregation containing DISTINCT keywords, and had better using aliasing and one more column (tbl_school.school_nm) within the GROUP BY list to make it a more proper SQL( Btw some DBMS don't allow excluding that column from GROUP BY while MySQL allows ) :
SELECT s.school_id, s.school_nm,
COUNT(DISTINCT c.class_id) AS class,
COUNT(DISTINCT t.teacher_id) AS teacher,
COUNT(DISTINCT d.student_id) AS student -- this is a presumedly existing column within the student table
FROM tbl_school s
JOIN tbl_teacher t ON s.school_id = t.school_id
JOIN tbl_class c ON t.teacher_id = c.teacher_id AND s.school_id = c.school_id
JOIN tbl_student d ON c.class_id = d.class_id
GROUP BY s.school_id, s.school_nm
Welcome to SO.
It has been a while since I have done this, but have you tried adding a WHERE modifier to your internal SQL select statements? Like this...
Side note: It makes more sense, to me, to also have a FK on tbl_student that links them to which school that they're in.
SELECT
tbl_school.school_id,
tbl_school.school_nm,
(SELECT COUNT(*) FROM tbl_class WHERE school_id=tbl_school.school_id) AS class,
(SELECT COUNT(*) FROM tbl_teacher WHERE school_id=tbl_school.school_id) AS teacher,
(SELECT COUNT(*) FROM tbl_student) AS student
FROM
tbl_school
INNER JOIN tbl_teacher ON tbl_school.school_id = tbl_teacher.school_id
INNER JOIN tbl_class ON tbl_teacher.teacher_id = tbl_class.teacher_id AND tbl_school.school_id = tbl_class.school_id
INNER JOIN tbl_student ON tbl_class.class_id = tbl_student.class_id
GROUP BY
tbl_school.school_id

SQL query find records that not persists in other tables

I need to print all persons which are not students and not teachers. I have three tables. Oracle database. Code so far:
SELECT PersonID, FirstName, LastName, Gender, DateOfBirth
FROM PERSON
INNER JOIN STUDENT S ON PERSON.PersonID = S.StudentID
INNER JOIN TEACHER T ON PERSON.PersonID = T.TeacherID
WHERE PERSON.PersonID != S.StudentID
AND PERSON.PersonID != T.TeacherID;
I guess my query is wrong because it returns 0 results. Do you have any idea what must I change?
" my query is wrong because it returns 0 results"
Inner joins return records when there is a match. You're trying to find PERSON records which join to neither STUDENT nor TEACHER. So, change your query to use outer joins:
SELECT PersonID, FirstName, LastName, Gender, DateOfBirth
FROM PERSON
LEFT OUTER JOIN STUDENT S ON PERSON.PersonID = S.StudentID
LEFT OUTER JOIN TEACHER T ON PERSON.PersonID = T.TeacherID
WHERE S.StudentID is null
AND T.TeacherID is null;
This is an anti-join: it returns records from PERSON which don't match records in STUDENT and TEACHER.
Use not exists:
select p.*
from person p
where not exists (select 1 from teacher t where t.teacherid = p.personid) and
not exists (select 1 from students s where s.studentid = p.personid);
Although you can write this query with left join, I think the version using not exists is almost a direct translation of the question, making it easier to understand.
In Oracle, you can also write this using minus -- if you want only the id:
select personid
from person
minus
select teacherid
from teacher
minus
select studentid
from student;
--Try this with Left Outer Join...
SELECT
P.PersonID,
P.FirstName,
P.LastName,
P.Gender,
P.DateOfBirth
FROM PERSON P
LEFT OUTER JOIN STUDENT S ON P.PersonID = S.StudentID
LEFT OUTER JOIN TEACHER T ON P.PersonID = T.TeacherID
WHERE S.PersonID is null and T.PersonID is null

How to merge data from multiple tables in SQL

Guess I am in a complex situation. Heres the scene.
I have 3 tables in SQL Server.
Enrollment, Student, Course. (FYI, there are no foreign keys)
The table columns are
Student - StudentId, StudentName
Course - CourseId, CourseName
Enrollment - EnrollmentId, StudentId, CourseId, CourseResult
Sample Data
Student - s1, Sid
Course - c1, Science
Enrollment - 1, s1, c1, 80
I would want a SQL query that selects data like below
1, s1, Sid, c1, Science, 80
I did it hard way in the DAL layer with multiple calls to database. But would like to do it in one call, and in DB.
Any one for the rescue!
Use a join.
select enrollment.*, student.*, course.* from enrollment
inner join Student on enrollment.studentId = student.studentId
inner join Course on enrollment.courseId = course.courseId
There actually are foreign keys in your data model. They may not be marked as such in the db or you don't realize it. I also think it would become clearer if in your list you put the Enrollment table second, between Student and Course. Enrollment is the table that links a student to a course.
I think you just want an inner join on the three tables like this:
SELECT e.EnrollmentId, s.StudentId, c.CourseId, c.CourseName, e.CourseResult
FROM Student AS s
JOIN Enrollment AS e ON s.StudentId = e.StudentId
JOIN Course AS c on e.CourseId = c.CourseId
Seems like a few simple JOINs would do it...
select
e.EnrollmentId
,s.StudentId
,s.StudentName
,c.CourseId
,c.CourseName
,e.CourseResult
from Enrollement e
inner join Course c on e.CourseId = c.CourseId
inner join Student s on e.StudentId = s.StudentId
Try:
SELECT e.EnrollmentId, s.StudentId, s.StudentName, c.CourseId, c.CourseName, e.CourseResult
FROM Student s JOIN
Enrollment e ON s.StudentId = e.StudentId JOIN
Course c ON e.CourseId = c.CourseId

mysql - three joins on the same table

I have two tables:
persons
- person_id
- fullname
students
- student_id
_ person_id
- father_id
- mother_id
In students table the last three columns store ids from persons table. What SELECT could retrieve the following data:
- student name
- father name
- mother name
We assume no WHERE, ORDER BY, or LIMIT for simplicity
try this:
select sp.fullname studentname, fp.fullname fathername, mp.fullname mothername
from students s
inner join persons sp on (s.student_id = sp.person_id)
inner join persons fp on (s.father_id = fp.person_id)
inner join persons mp on (s.mother_id = mp.person_id)
Try below query -
SELECT p.fullname,m.fullname,f.fullname from students s
LEFT JOIN persons p ON s.person_id = p.id
LEFT JOIN mother m ON s.mother_id = m.id
LEFT JOIN father f ON s.father_id = f.id
WHERE s.student_id = 'id of which student record you want';