SQL view all courses for one student - mysql

I have 3 tables
table_student
ID, firstname, lastname
table_courses
ID, course_name
table_student_course
ID, student_ID, course_ID, date_taken
All I want to do is list all courses by course_name and date_taken by student with ID=1
Anyone please?

You need to use the JOIN on the table_courses and table_student_course tables and then apply the Order By on cource_name to sort out by course name.And for selecting the particular student apply the Where clause as filter.
SELECT
t.course_name,
tsc.date_taken
FROM
table_courses t INNER JOIN table_student_course tsc
ON t.ID = tsc.course_ID
WHERE
tsc.student_ID = 1
ORDER BY
t.course_name
If you also want to get the students detail from the query then you need to join the 3 tables like below,
SELECT s.firstname, s.lastname, c.course_name, sc.date_taken
FROM table_courses c
INNER JOIN table_student_course sc ON c.ID = sc.course_ID
INNER JOIN table_student s ON sc.student_ID = s.ID
WHERE sc.student_ID = 1
ORDER BY c.course_name

SELECT s.firstname, s.lastname, c.course_name, sc.date_taken
FROM table_courses c
INNER JOIN table_student_course sc ON c.ID = sc.course_ID
INNER JOIN table_student s ON sc.student_ID = s.ID
WHERE sc.student_ID = 1
ORDER BY c.course_name

By using Inner Join on the tables "table_courses" & "table_student_course" we selects all rows from both tables as long as there is a match between the columns in both tables making sure the ids are the same. If the condition is met( student_id=1) then the query will return what is expected.
SELECT course_name, date_taken
FROM table_courses c INNER JOIN table_student_course sc ON c.id = sc.course_id
WHERE sc.student_ID = 1
ORDER BY course_name

Related

create a table based on other tables

I have 4 different tables:
student: sid, name, gender
grades: sid, grade
address: postcode, sid, distance_to_school
health_condition: sid, health_code
Now I want to make a new table that contains all of the columns that I mentioned above. I need to join them based on the sid. I tried to add columns separately but the code is really long. So is there another way to do this task?
If you want to show the data from the fifth table that you want to create, I think with the query is better, so you don't need the fifth table. Just
"SELECT * FROM student s
INNER JOIN grades g
on s.sid = g.sid
INNER JOIN address a
on s.sid = a.sid
INNER JOIN health_condition h
on s.sid = h.sid
ORDER BY sid ASC";
Please use below query will give you the exact result set.
SELECT t1.sid, t1.name, t1.gender , t2.grade,t3.postcode, t3.distance_to_school,
t4.health_code AS
student as t1 inner join grades t2 on t1.sid=t2.sid
inner join address as t3 on t3.sid= t1.sid
inner join health_condition as t4 on t4.sid=t1.sid
Try this query
FROM student s
LEFT JOIN grades g on g.sid = s.sid
LEFT JOIN address a on a.sid = s.sid
LEFT JOIN health_condition h on h.sid = s.sid
WHERE s.sid = ;

Given the following schema, what would be the query to print all students in a teachers class?

Schema:
This is what I'm thinking, but I don't think its right:
SELECT distinct t.teacherid, s.fname
FROM tea_cou t, students s, stu_cou c
WHERE t.courseid = c.courseid
You have to join the tables and then filter by teacher name.
SELECT S.*
FROM Teachers T
INNER JOIN Tea_Cou TC ON Tc.TeacherId = T.TeacherId
INNER JOIN Courses C ON C.CourseId= TC.CourseId
INNER JOIN Stu_Cou SC ON SC.CourseId = C.CourseId
INNER JOIN Students S ON S.StudentId = SC.StudentId
WHERE T.LNAME= 'name'

Is this the right way to join tables to fetch data?

I have a database with the tables:
Student(SID,Name,Surname,Age)
Registration(StudentID,CourseID)
Course(CID,Name,Cost)
I would like to extract only the name of the courses with students younger than 20. Will the query below do just that?
SELECT C.NAME
FROM Course C
INNER JOIN Registration
INNER JOIN Student S
WHERE CID = CourseID
AND SID = StudentID
AND Age < 20
GROUP BY C.NAME
I would also like to extract the number of students in each course having students younger than 20. Is it correct to do it as below?
SELECT count(S.NAME)
,C.NAME
FROM Student S
INNER JOIN Course C
INNER JOIN Registration
WHERE Age < 20
AND CID = CourseID
AND SID = StudentID
GROUP BY C.NAME
You are missing the ON part for the join otherwise it would just be a CROSS JOIN.
Your first query should look like this if you want just a distinct list of student names:
SELECT DISTINCT C.NAME
FROM Course C
INNER JOIN Registration R ON C.CID = R.CourseID
INNER JOIN Student S ON R.StudentID = S.SID
WHERE Age < 20
Your second query shouldn't really have the C.Name in the select if you want to get just a count unless you want a count of how many students have that name.
SELECT count(*)
FROM Student S
INNER JOIN Registration R ON s.SID = R.StudentID
INNER JOIN Course C ON c.CID = R.CourseID
WHERE Age < 20
GROUP BY C.NAME
First join these tables, then group by Course's PK(CID), Add the HAVING condition to filter the course which has students younger than 20.
Then use Course table to join the result to get the course name and count of students in the course.
SELECT
T1.Name,
T2.StudentCount
FROM
Course T1
INNER JOIN (
SELECT
c.CID,
COUNT(s.SID) AS StudentCount
FROM
Course c
LEFT JOIN Registration r ON c.CID = r.CourseID
LEFT JOIN Student s ON s.SID = r.StudentID
GROUP BY c.CID
HAVING COUNT(IF(s.Age < 20, 1, NULL)) > 0
) T2 ON T1.CID = T2.CID
More correctly, you should move the conditions of the join, to the join statements themselves by including them in the on clause instead of the where. While the results may not change in this instance, if you were to start including outer joins you would encounter difficulties.
SELECT count(S.NAME)
,C.NAME
FROM Student S
INNER JOIN Registration R
ON s.SID = R.StudentID
INNER JOIN Course C
ON c.CID = R.CourseID
WHERE Age < 20
GROUP BY C.NAME
There's a fiddle here showing it in action: http://sqlfiddle.com/#!9/c3b8f/1
Your first query will also produce the results you want, but again, you should move the join predicates to the join itself. Also, you don't need to perform the grouping just to get distinct values, mysql has an expression for that called distinct. So rewritten, the first query would look like:
SELECT DISTINCT C.NAME
FROM Student S
INNER JOIN Registration R
ON s.SID = R.StudentID
INNER JOIN Course C
ON c.CID = R.CourseID
WHERE Age < 20.
Again, the results are the same as what you have already but it is easier to 'read' and will put you in good stead when you move on to other queries. As it stands you have mixed implicit and explicit join syntax.
This fiddle demonstrates both queries: http://sqlfiddle.com/#!9/c3b8f/4
edit
I may have misinterpreted your original question - if you want the total number of students enrolled in a course with at least one student under 19, you can use a query like this:
select name, count(*)
from course c
inner join registration r
on c.cid = r.courseid
where exists (
select 1
from course cc
inner join registration r
on cc.cid = r.courseid
inner join student s
on s.sid = r.studentid
where cc.cid = c.cid
group by cc.cid
having min(s.age) < 20
)
group by name;
Again with the updated fiddle here: http://sqlfiddle.com/#!9/c3b8f/17

How to triple join tables to find and find entries that match two things?

I have a simple problem that's hard to describe (at least for me).
Consider the following schema for a database modeling courses:
COURSE (cid, did, name, num, creditHours),
STUDENT (sid, fname, lname, did)
ENROLLED_IN (eid, sid, cid)
What is a query that will find the sid of the students enrolled in course.name=Math" and "Science"?
I'm sorry i asked a similar (simpler) question thinking I could figure the rest out but I could not: https://stackoverflow.com/questions/18902489/how-to-find-entries-in-database-that-meet-multiple-matches
AS the other page suggests, you need to do two JOIN's to the same table. But since you want to use the Name and not the cid, you join to the COURSE based on the enrollment data.
SELECT DISTINCT s.sid
FROM STUDENT s
INNER JOIN ENROLLED_IN e ON e.sid = s.sid
INNER JOIN COURSE c ON c.cid = e.cid AND c.Name = 'Math'
INNER JOIN COURSE c2 ON c2.cid = e.cid AND c2.Name = 'Science'
If you need the whole student record, then...
SELECT STUDENT.*
FROM STUDENT
INNER JOIN
(SELECT DISTINCT s.sid
FROM STUDENT s
INNER JOIN ENROLLED_IN e ON e.sid = s.sid
INNER JOIN COURSE c ON c.cid = e.cid AND c.Name = 'Math'
INNER JOIN COURSE c2 ON c2.cid = e.cid AND c2.Name = 'Science'
) t0 ON t0.sid = STUDENT.sid
EDIT Instead of DISTINCT you could also use GROUP BY, ala
SELECT s.sid
FROM STUDENT s
INNER JOIN ENROLLED_IN e ON e.sid = s.sid
INNER JOIN COURSE c ON c.cid = e.cid AND c.Name = 'Math'
INNER JOIN COURSE c2 ON c2.cid = e.cid AND c2.Name = 'Science'
GROUP BY s.sid
EDIT and instead of using two joins, you can use HAVING clauses
SELECT s.sid
FROM STUDENT s
INNER JOIN ENROLLED_IN e ON e.sid = s.sid
INNER JOIN COURSE c ON c.cid = e.cid
WHERE c.Name IN ('Math', 'Science')
GROUP BY s.sid
HAVING COUNT(*) = 2

Many to many query with filter

I have following issue. There are two tables - groups and students and third pivot table group_student.
Query to get students from specific groups (id:1,8) is clear...
SELECT DISTINCT s.*
FROM students AS s
Inner Join group_student AS gs ON gs.student_id = s.id
Inner Join groups AS g ON g.id = gs.group_id
WHERE g.id IN ("1","8")
It works. But, how to query, if I want to select just segment of students of group id 1. For example s.name = "john". So the result should be: all students from group id 8 + all students with name "john" from group id 1.
Thanx for posts :-)
Try this:
SELECT DISTINCT s.*
FROM students AS s
Inner Join group_student AS gs ON gs.student_id = s.id
Inner Join groups AS g ON g.id = gs.group_id
WHERE g.id ="8" or (g.id="1" and s.name = "john")
you can use UNION too
SELECT DISTINCT s.*
FROM students AS s
Inner Join group_student AS gs ON gs.student_id = s.id
Inner Join groups AS g ON g.id = gs.group_id
WHERE g.id = 8
UNION
SELECT DISTINCT s.*
FROM students AS s
Inner Join group_student AS gs ON gs.student_id = s.id
Inner Join groups AS g ON g.id = gs.group_id
WHERE gp.id="1" and s.name = "john"
One more option, avoiding DISTINCT and the (probably unneeded) join to groups:
SELECT s.*
FROM students AS s
WHERE EXISTS
( SELECT *
FROM group_student AS gs
WHERE gs.student_id = s.id
AND ( gs.group_id = 8
OR (gs.group_id, s.name) = (1, 'john')
)
)