The situation is like this:
There is Teacher Performance and Student Performance entity, so teacher and student may attend same course have their score
Teacher can teach student and teacher
There is a Teaching Relation table, and yes both teacher and student can appear in attendance column, but only teacher can appear in teacher column.
The desired report table is list all teacher's performance, plus average performance of the students and teachers who are taught by the teacher.
In our system the id is numeric, I made it first name just for demo purpose.
Teacher Performance(tb_tp)
t_id | score
------------------
JOHN | 5
ASHLEY | 6
STEVEN |4.5
Student Performance(tb_sp)
s_id | score
------------------
SCOTT | 5
FRANK | 8
TIM | 7
Teaching Relation(tb_tr)
t_id (teacher) | a_id for attendance id | a_type attendance type
------------------------------------------------------------------
ASHLEY | JOHN | teacher
ASHLEY | FRANK | student
ASHLEY | TIM | student
JOHN | ASHLEY | teacher
JOHN | FRANK | student
Desired Report:
t_id | Score| avg_t AVG score from Teacher | avg_s AVG score from Student
--------------------------------------------------------------------------
ASHLEY | 6 | (5 from John) /1 | (8 from Frank + 7 from Tim)/2
--------------------------------------------------------------------------
JOHN | 5 | (6 from ASHLEY) /1 | (8 from Frank) / 1
How can we make this happen? I am thinking two joins together or union two queries, but either way cannot keep the result on the same row and be accurate
I think the technique you want is two outer joins with an aggregate. Here is my untested pass at it:
SELECT p.t_id, p.score, scores.avg_teacher_score, scores.avg_student_score
FROM teacher_performance p
JOIN (
SELECT t_id, AVG( t.score) AS avg_teacher_score, AVG( s.score ) AS avg_student_score
FROM teaching_relation tr
LEFT JOIN teacher_performance t ON t.t_id = tr.a_id AND tr.a_type='teacher'
LEFT JOIN student_performance s ON s.s_id = tr.a_id AND tr.a_type='student'
) scores
ON scores.t_id = p.t_id
Related
Ok, I have two tables.
1 lists a bunch of courses and their details.
1 lists a bunch of curriculums and their associated connections.
I need to create a query that will list the curriculum name, LIST ALL COURSES, and then indicate if the course is in the Curriculum (TRUE) or not present (FALSE).
Here is what I have tried so far.
Left Outer Join for courses table since I want ALL the courses compared to the curriculums
Count number of curriculum ids for each course - DOESN'T WORK ONLY RETURNS '1' VALUES; AND ONLY SHOWS COURSES IN THE CURRICULUM
Finding Differences Between Two Tables - DOESN'T WORK, ONLY SHOWS VALUES WITH NO CURRICULUMS.
Tried an IIF(IS NULL) calculation - DOESN'T WORK ONLY RETURNS 'TRUE' VALUES; AND ONLY SHOWS COURSES IN THE CURRICULUM.
This should be easy. Can someone help me create the query. Basically put I need all values from BOTH tables showing up and then showing where the value is NULL in relation to the courses.
Table 1:
COURSE ID COURSE NAME
1 ENGLISH
2 FRENCH
3 DRAWING
4 SKETCHING
Table 2
Curriculum ID Curriculum NameID Course ID
1 Senior (actually #) 1
2 Senior 3
3 Junior 1
4 Junior 2
5 Junior 3
Results
Curriculum Name Course Name In Curriculum
Senior English True
Senior French False
Senior Drawing True
Senior Sketching False
Junior English True
Junior French True
Junior Drawing True
Junior Sketching False
TJ
Since you essentially have a many-to-many relationship between courses & curriculums (a course could appear on several curriculums, and a curriculum could contain several courses), I would suggest structuring your data in the following manner:
Table: Courses
+-------+-----------+
| Co_ID | Co_Desc |
+-------+-----------+
| 1 | English |
| 2 | French |
| 3 | Drawing |
| 4 | Sketching |
+-------+-----------+
Table: Curriculums
+-------+---------+
| Cu_ID | Cu_Desc |
+-------+---------+
| 1 | Junior |
| 2 | Senior |
+-------+---------+
Junction Table: Curriculum_Courses
+----------+----------+
| CC_Cu_ID | CC_Co_ID |
+----------+----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 3 |
+----------+----------+
Then, your query is relatively easy to construct as you can use a combination of a cross-join and left-join in the following manner:
select
t.cu_desc as [Curriculum Name],
t.co_desc as [Course Name],
not cc_cu_id is null as [In Curriculum]
from
(select * from curriculums, courses) t left join curriculum_courses u on
t.cu_id = u.cc_cu_id and
t.co_id = u.cc_co_id
order by
t.cu_id, t.co_id
From this table of football players, how would you select the players' names alongside their captains' names?
PlayerID | PlayerName | TeamCaptainID
=====================================
1 | Jay | 5
2 | John | 3
3 | James | 3
4 | Jack | 5
5 | Jeremy | 5
The result I'm after is:
Player | Captain
================
Jay | Jeremy
John | James
James | James
Jack | Jeremy
Jeremy | Jeremy
Applying inner join on the same table seems to be enough:
select t1.PlayerName as Player
, t2.PlayerName as Captain
from tbl t1
join tbl t2 on t1.TeamCaptainID = t2.PlayerID
To find the exact result you want, you have to use self-join, it is how this will work:
To achieve the desired outcome, we will use the same table twice and in order to do this we will use the alias of the table, a self join must have aliases.
To get the list of Players and their captain the following sql statement can be used :
SELECT a.PlayerName AS "Player",
b.TeamCaptainID AS "Captain"
FROM team a, team b
WHERE a.TeamCaptainID=b.PlayerName
I have 3 tables in my database.
One is for activities, another one is for students and the last one is for the student's score in an activity. So one activity can have one or more student's scores, and one student has one score in one activity.
So I need to show a list of activities of student's course even if he has not score yet. But, if the student has a score in some activity, I must only show that student's score.
My problem is that when I select the student's score, I need to add a 'where' condition to select only his scores, but if he has not score yet, I have no records in my results. How can I select all activities of a course and only if the student has score, then select only his score for that activity?
Activity Table:
id | name | score
1 | first exam | 30
2 | second exam | 30
3 | final exam | 40
Student Table:
id | name
1 | Jhon
2 | Sam
3 | Frank
Student's Score Table:
id | activity | student | score
1 | 1 | 1 | 16
2 | 1 | 2 | 17
3 | 1 | 3 | 15
So, if Jhon enter to the system and want to see activities's course, he should see a list of all activities but only his score. For example this list:
Activity | Score | Your Score
First Exam | 30 | 16
Second Exam | 30 | -
Final Exam | 40 | -
You want a left outer join:
select a.activity_id, coalesce(acs.score, 0) as thescore
from activities a left outer join
activityscores acs
on a.activity_id = acs.activity_id and
acs.student_id = THESTUDENTID;
If a student can have more than one score in an activity, then you would want an aggregation as well.
Hi New comer to Stack overflow so if I do not present this correctly I am sorry.
I have used Google, W3schools and read the FQA on SQL.
I am running SQL using the SQL command line in WAMP2.0. I am currently doing a project where the aim is to create a min University DB. With students, grades, programmes, modules ect
One of the tasks is to to list all the students, there modules and there correspoding grades. To do this I am trying to use a JOIN command to select all the names from the Students table, with all there corresponding modules + grades from the records table.
+------------+-------+------------+-----------------+
| Student_id | Name | DOB | Address |
+------------+-------+------------+-----------------+
| 4665236 | Paddy | 1985-09-18 | 123 Fake Street |
| 5665236 | Paul | 1984-06-12 | Good manlane |
| 6665236 | John | 1984-03-09 | Docotor town |
| 7665236 | Aidan | 1983-07-09 | Banker worlds |
| 8665236 | Joe | 1983-07-09 | 24 hitherwood |
+------------+-------+------------+-----------------+
+------------+--------+------+-------+
| Student_id | Mod_id | GPA | Grade |
+------------+--------+------+-------+
| 4655236 | 2222 | 3.84 | A- |
| 5655236 | 11111 | 3.44 | B+ |
| 6655236 | 33333 | 3.24 | B |
| 7655236 | 44444 | 2.45 | C- |
| 8655236 | 44444 | 2.45 | C- |
+------------+--------+------+-------+
The PRIMARY KEY in the students table is Student_id INT 11
The PRIMARY KEY for records is (Student_id,Mod_id)
Individual SELECT FROM , statements work fine on both tables.
Issue occurs when I use
SELECT students.Name, records.Grade
FROM students
INNER JOIN records
ON students.Student_id=Student_id
ORDER BY students.Name
I get the following error
ERROR 1052 (23000): Column 'Student_id' in on clause is ambiguous
Thanks for amazingly fast response I tried
SELECT students.Name, records.Grade
FROM students
INNER JOIN records
ON students.Student_id=records.Student_id
ORDER BY students.Name;
And Got ---- Empty set (0.00 sec) ?
You have to qualify that column Student_Id with an alias, something like records.studentId so that it will be un ambiguous in the ON clause, or:
SELECT s.Name, r.Grade
FROM students AS s
INNER JOIN records AS r ON s.Student_id= r.Student_id
ORDER BY s.Name
You need to supply the table name for column Student_id to avoid ambiguity because it both exist on the two tables.
SELECT students.Name, records.Grade
FROM students
INNER JOIN records
ON students.Student_id = records.Student_id -- << THIS
ORDER BY students.Name
The reason you're column name is being flagged as ambiguous is because you've got two different tables that each have the Student_id field. You can join a table to itself, so even though you've got an identifier on the first instance of the field you need one on both.
Try the following code:
SELECT students.Name, records.Grade
FROM students
INNER JOIN records
ON students.Student_id=records.Student_id
ORDER BY students.Name
You can also alias the tables if that helps your code look cleaner by using the following:
SELECT s.Name, r.Grade
FROM students s
INNER JOIN records r
ON s.Student_id=r.Student_id
ORDER BY s.Name
However, this only works if the Student IDs match in both tables. in the example data you've presented there are no matching records. 4665236 != 4655236
What is the most efficient way to get data from two tables set up in the following way:
Table 1:
ID(PK) | Name | Age
--------------------------
1 | Jim | 44
2 | Jane | 35
3 | John | 22
Table 2
Name(PK) | Pet(PK)
-----------------
Jim | Cat
Jim | Dog
Jane | Fish
There is a constraint on "Name" with the FK in Table 2
Results
I want the age and all the pets for a specific person.
Name | Age | Pet
---------------------
Jim | 44 | Cat
Jim | 44 | Dog
As I see it these are my options:
1) Left join table 2 on Name and end up with redundant data in my resulting array for Name and Age (as above).
2) Use a function that turns the pets into a comma separated list.
3) Use 2 separate selects.
My question is relating to performance of the 3 options above. I don't need SQL (specifically, unless you want to suggest another method).
Thanks!
select
tb01.name, tb01.age, tb02.pet
from
table01 tb01
left join table02 tb02 on tb02.name = tb01.name