I have 3 tables teacher subject and assignments. When a teacher logs in, I want to display all the subjects regardless if he is the teacher and regardless if there is related records or not. If there is no related records (assignments) i want it to display 0.
Teacher Table: Teacher_PK, Teacher_name
Subject Table: Subject_PK, Teacher_fk, Subject_name,
Assignments Table: Assignment_PK, Subject_fk, assignment_name
Right now i have it like this:
"SELECT *, count(a.subject_fk)
FROM assignment AS b
LEFT OUTER JOIN subject AS a
ON a.subject_fk = b.subject_PK
WHERE a.teacher_fk = $sessionVar
GROUP BY b.subject_fk
ORDER BY b.subject_name ASC";
The problem with this query is that it does not show all subjects, it only shows the subject if there are related tables.
English (3)
Math(2)
What i want it to display is
English(3)
Math(2)
Gym(0)
Science(0)
Thank you for any help.
All subjects in the Subject table
SELECT
s.*,
count(a.assignment_pk) as numAssignments
FROM
Subject s
LEFT OUTER JOIN Assignments a ON
s.Subject_pk = a.Subject_fk AND
a.teacher_fk = $sessionVar
GROUP BY
s.*
ORDER BY
s.subject_name ASC
edit - moved the filter on teacher id to the outer join section
Related
I am a beginner with SQL syntax. I have 2 tables called STUDENT and EXAMINATION and I am, in 1 line, trying to write a query to print ID, SUBJECT and NUMBER_OF_TIMES. I am not told which column belongs to which table but my guess is that ID belongs to STUDENT and SUBJECT belongs to EXAMINATION. NUMBER_OF_TIMES is just how many times the same student has taken that subject exam.
I tried SELECT STUDENT.ID, EXAMINATION.SUBJECT, NUMBER_OF_TIMES but no luck.
Your working query would look something like this:
SELECT
s.ID,
e.SUBJECT,
COUNT(e.STUDENT_ID) AS cnt
FROM STUDENT s
LEFT JOIN EXAMINATION e
ON s.ID = e.STUDENT_ID
GROUP BY
s.ID,
e.SUBJECT
This answer assumes, really out of necessity, that there exists a join column STUDENT_ID in the exam table, which connects with the student table. We use a left join so as to report all students, even those with a zero count.
I have a question regarding MySql statement. I have 2 tables, record and training. Training table contains list of all courses, and record table contains list of courses that the user have attend. Training table is below
Record table format:
I want to get list non attending courses of each user. For eg: From the above table structure, user 277 is attending 130,167,128 & 2. So the non attending courses of user 277 is 3,4,5,7,8,9,147,11,12.
How can i write sql statement for getting the above result? Please help
Its something like this
SELECT * FROM training t WHERE t.id NOT IN (select trainingId from record where UserId=277 && piId=1) && t.status=1 ORDER BY t.categoryId
select id from training where id not in ( select trainingid from record where userid = yourid)
Get a list of users, cross join that with the training courses and then LEFT OUTER JOIN that to the table of training courses done by users. Us the WHERE clause to check there wasn't a match to the last table.
Untested, but something like this:-
SELECT sub_user.UserId, t.id
FROM
(
SELECT DISTINCT UserId from record
) sub_user
CROSS JOIN Training t
LEFT OUTER JOIN Record r
ON sub_user.UserId = r.UserId
AND r.trainingId = t.id
WHERE r.id IS NULL
If you have a table of users (which you probably do) then you could eliminate the sub query and replace it with that table.
I have the two tables STUDENT and TaskEffort.
Many students have worked on same tasks. For a particular task the name of the students and effort should be considered.
The STUDENT table contains studentid, firstName and lastName.
The TaskEffort table contains taskid, studentid and Effort
I need to display the taskid, first name, last name, effort, for those who worked on a particular task.
This is one of the queries I tried, but this is not working.
SELECT t.id, s.firstname, s.lastname, t.effort
FROM taskeffort t
LEFT OUTER JOIN student s ON t.id = 4 AND s.studentid = t.studentid
Thanks in advance.
First the design is not accurate.
You said that "Many students must have worked on same task" but your design is
1-many students. It means that each task has only one student. You need to change the design to support you requirements.
this relation is many-to-many. Student can be assigned to many tasks and tasks may have been assigned to many students.
Add a third table called taskAssignments with columns: student_id,task_id and remove student_id column from TaskEffort.
Then run this query:
SELECT t.id, s.firstname, s.lastname, t.effort
FROM TaskEffort t
LEFT JOIN taskAssignments ta ON t.id=ta.task_id
LEFT JOIN student s ON s.studentid = ta.studentid
WHERE t.id = 4
SELECT t.id, s.firstname,s.lastname, t.effort
FROM taskeffort t
LEFT OUTER JOIN student s ON s.studentid = t.studentid
WHERE t.id = 4;
I have two tables - one for courses and one for people attending the course.
Both are joined by course_id
table 1: firstaid - has all the course names
table 2: first_aid_att - records attendees and captures first aid
course id
I would like to get a count of attendees per course.
I have got a join working but don't know how to do the group by and count.
SELECT *
FROM firstaid
LEFT JOIN first_aid_att ON firstaid.course_id = first_aid_att.course_id
ORDER BY `sortDate` ASC
Try this:
SELECT f1.*, COUNT(f2.course_id)
FROM firstaid f1
LEFT JOIN first_aid_att f2 ON (f1.course_id = f2.course_id)
GROUP BY f1.course_id
ORDER BY f2.sortDate
I have the following 4 tables:
Teacher: id, teacher
Student: id, student
Quiz: id, teacher_id, answer, dis_1, dis_2, dis_3
Intermediate: id, student_id, teacher_id, score
Teachers create quizzes and students take quizzes. The intermediate table keeps track of the scores on quizzes with the relevant IDs.
I would like to return all the quizzes and indicate either the student's score or that they haven't taken it.
If they haven't taken the quiz, then the Intermediate table will not have an entry for that student. If they have take the quiz, then the Intermediate table will have the score.
This is my statement so far:
SELECT Quiz.question as question,
Quiz.id as id, Quiz.title as title,
Quiz.teacher_id as teacher_id, Teacher.teacher as teacher,
Quiz.answer as answer, Quiz.dis_1 as dis1,
Quiz.dis_2 as dis2, Quiz.dis_3 as dis3,
Intermediate.score as score
FROM Teacher, Intermediate
RIGHT JOIN Quiz ON Quiz.id = Intermediate.quiz_id
RIGHT JOIN Student ON Student.id = Intermediate.student_id
WHERE Quiz.teacher_id = Teacher.id
When I try that statement I get all of the quizes taken and it displays the score for whoever just took it. I want it to just display the score if it exists in the Intermediate table.
You appear to be close. One thing that may be causing you issues is:
FROM Teacher, Intermediate
When you combine tables without using the explicit INNER/RIGHT/LEFT JOIN syntax, it can often lead to undesired results, especially for outer joins. You can read more about MySQL JOINS which may help as you move forward.
You also did not have the student's name in your select, which I added so you see the name of the person associated with the score. If you have a student that has not taken a quiz, their name, and score, will be NULL, due to how a LEFT OUTER JOIN works (Returning all the rows from the left table, and matching rows or NULL for the right table)
SELECT q.question, q.id, q.title, q.teacher_id, t.teacher
, q.answer, q.dis_1, q.dis_2, q.dis_3, s.student, i.score
FROM Quiz AS q
LEFT OUTER JOIN [Intermediate] AS i ON q.id = i.quiz_id
LEFT OUTER JOIN Teacher AS t ON i.teacher_id = t.teacher_id
LEFT OUTER JOIN Student AS s ON i.student_id = s.student_id
WHERE Quiz.teacher_id = Teacher.id this is converting your right joins into inner joins.
Also I find it difficult to reason about RIGHT JOINS so I've converted it to LEFT JOINS
SELECT
Quiz.question as question,
Quiz.id as id, Quiz.title as title,
Quiz.teacher_id as teacher_id, Teacher.teacher as teacher,
Quiz.answer as answer, Quiz.dis_1 as dis1,
Quiz.dis_2 as dis2, Quiz.dis_3 as dis3,
Intermediate.score as score
FROM
student
LEFT JOIN Intermediate
ON Student ON Student.id = Intermediate.student_id
LEFT JOIN Quiz
ON Quiz.id = Intermediate.quiz_id
LEFT JOIN Teacher
ON Quiz.teacher_id = Teacher.id
You might also want to add something from Student so you don't end up with a bunch of nulls
You might also want to add a Case Statement like this to the select statement
CASE WHEN Intermediate.score is null then 'not taken' else 'taken' end IsTaken