joining one table to multi others - mysql

i have 3 tables as the following:
STUDENT
---------------
id name
---------------
1 Joe
2 mark
3 mike
---------------
SUBJECT
-----------------------------------
id student_id name
-----------------------------------
1 1 math
2 1 english
3 1 french
4 1 history
5 2 math
6 2 english
7 2 french
8 3 math
9 3 english
-----------------------------------
EXAM
-----------------------------------
ID Student_id mark
-----------------------------------
1 1 10
2 1 10
3 1 10
4 1 10
5 2 5
6 2 5
7 2 5
8 3 2
9 3 2
-----------------------------------
SELECT
student.id, student.name AS 'NAME',
COUNT(subject.id) AS 'SUBJECTS',
SUM(exam.mark) AS 'MARKS'
FROM
'student'
INNER JOIN subject
ON subject.student_id = student.id
LEFT JOIN exam
ON exam.student_id = student.id
GROUP BY
student.id
i want to join between STUDENT and SUBJECT, STUDENT and EXAM
i problem is happening when i join the third table, it
duplicates the results.
i succeeded to join the first two tables, but when i join > the third one with them, it duplicates the counts.
the result i need is:
-----------------------------------
ID NAME SUBJECTS MARKS
-----------------------------------
1 joe 4 40
2 mark 3 15
3 mike 2 4

One simple approach here is to do separate aggregations on the subject and exam tables, and then join them:
SELECT
s.id,
s.name AS NAME,
COALESCE(su.cnt, 0) AS SUBJECTs,
COALESCE(e.marks, 0) AS MARKS
FROM student s
LEFT JOIN
(
SELECT student_id, COUNT(*) AS cnt
FROM subject
GROUP BY student_id
) su
ON s.id = su.student_id
LEFT JOIN
(
SELECT student_id, SUM(mark) AS marks
FROM exam
GROUP BY student_id
) e
ON s.id = e.student_id;
Demo
Note that I use left joins above, because perhaps a given student might not have any entry at all in either the subject or exam tables. In this case, we would assign his count/sum to zero by default.

You can get the aggregated columns by using a direct query for each student id:
select
s.id, s.name,
(select count(*) from subject where student_id = s.id) subjects,
(select sum(mark) from exam where student_id = s.id) marks
from student s
See the demo.

Related

Get record that has a record in different table but with different circumstances

studClassJunction
studID
classID
1
A
2
A
1
B
2
B
studOutput
studID
classID
actID
score
1
A
act1
23
1
A
act2
15
2
A
act2
16
1
B
act1
18
2
B
act1
18
userRecd
userID
frstnme
role
1
Carlos
student
2
Roberto
student
3
Lorem
teacher
My goal is to get all the students score and their names in a given activity stored in a specific classroom whether the student has a score or not.
The point is to show the teacher (the one viewing this) the students who has answered the activity and those who did not.
So, for example, get score and name for activity ID act1 for all students in class ID A.
Expected Output:
studID
frstnme
score
1
Carlos
23
2
Roberto
null
Since studID 1 has answered the activity, there's a value in the score column (23). However, studID 2 has only answered act2, and not act1, so they have a score of null, which I think can be changed to 0 through CASE expression.
How do I get this kind of result?
EDIT 1
This is my attempt so far in achieving this. It goes as follows:
SELECT SCJ.studID AS ID, UR.firstnme AS NAME, SO.score AS SCORE
FROM studClassJunction AS SCJ
INNER JOIN studOutput AS SO
ON SCT.classID = SO.classID
INNER JOIN userRecd AS UR
ON SCT.studID = UR.userID
WHERE (SO.actID = "act1" OR SO.actID IS NULL) AND SCJ.classID = "A"
This query will yield this result:
| ID | NAME | SCORE |
|-----------------|------------------|----------------|
| 1 | Carlos | 23 |
| 2 | Roberto | 23 |
For some reasons, instead of a null, my SQL query has also put 23 in studID 2's score column.
You aren't joining on student ID. If you do that, it should work.
SELECT SCJ.studID AS ID, UR.firstnme AS NAME, coalesce(SO.score, 0) AS SCORE
FROM studClassJunction AS SCJ
INNER JOIN studOutput AS SO
ON SCJ.classID = SO.classID and SCJ.studID = SO.studID
INNER JOIN userRecd AS UR
ON SCT.studID = UR.userID
WHERE (SO.actID = "act1" OR SO.actID IS NULL) AND SCJ.classID = "A"

SSRS - Repeated values in Matrix

I am very much a beginner at this, so please pardon my ignorance. I have searched for hours, but don't yet have the experience to have a better idea of precisely what to search for!
I have a data set in SSRS as follows:
|---------------------|------------------|
| Subject | Student |
|---------------------|------------------|
| Biology | Student A |
|---------------------|------------------|
| Chemistry | Student A |
|---------------------|------------------|
| Chemistry | Student B |
|---------------------|------------------|
| Physics | Student B |
|---------------------|------------------|
I want to write a matrix which counts all the students who are doing a combination of subjects (eg. Chemistry and Physics). Currently, my matrix is only counting the number of students in an individual subject, leading to something like this:
|---------------------|------------------|------------------|------------------|
| | Biology | Chemistry | Physics |
|---------------------|------------------|------------------|------------------|
| Biology | 20 | 0 | 0 |
|---------------------|------------------|------------------|------------------|
| Chemistry | 0 | 36 | 0 |
|---------------------|------------------|------------------|------------------|
| Physics | 0 | 0 | 16 |
|---------------------|------------------|------------------|------------------|
What am I missing?
First, your dataset needs to combine subjects as Subject1 and Subject2, for example by joining the table to itself on the Student field.
Then, in the matrix, use a row group that groups on Subject1 and a column group that groups on Subject2.
That's easy:
You inner join the map between student and subject with itselfs, but only if the student is the same, but the subject is different.
Then you do CountDistinct on the studentId in the report, doesn't matter if it's from map1 or map2, since it's always the same.
;WITH subjects AS
(
SELECT 1 AS subject_id, 'Biology' AS subject_name
UNION ALL SELECT 2 AS subject_id, 'Chemistry' AS subject_name
UNION ALL SELECT 3 AS subject_id, 'Physics' AS subject_name
)
,students AS
(
SELECT 1 AS student_id, 'Student A' AS student_name
UNION ALL SELECT 2 AS student_id, 'Student B' AS student_name
UNION ALL SELECT 3 AS student_id, 'Student C' AS student_name
UNION ALL SELECT 4 AS student_id, 'Student D' AS student_name
)
,map_student_subject AS
(
SELECT 1 AS student_id, 1 AS subject_id
UNION ALL SELECT 1 AS student_id, 2 AS subject_id
UNION ALL SELECT 2 AS student_id, 2 AS subject_id
UNION ALL SELECT 2 AS student_id, 3 AS subject_id
UNION ALL SELECT 3 AS student_id, 3 AS subject_id
UNION ALL SELECT 4 AS student_id, 3 AS subject_id
)
SELECT
map1.student_id AS map1_student_id
,map1_student.student_name AS map1_student_name
,map1.subject_id AS map1_subject_id
,map1_subject.subject_name AS map1_subject_name
,map2.student_id AS map2_student_id
,map2_student.student_name AS map2_student_name
,map2.subject_id AS map2_subject_id
,map2_subject.subject_name AS map2_subject_name
FROM map_student_subject AS map1
INNER JOIN map_student_subject AS map2
ON map2.student_id = map1.student_id
AND map2.subject_id <> map1.subject_id
LEFT JOIN students AS map1_student
ON map1_student.student_id = map1.student_id
LEFT JOIN students AS map2_student
ON map2_student.student_id = map2.student_id
LEFT JOIN subjects AS map1_subject
ON map1_subject.subject_id = map1.subject_id
LEFT JOIN subjects AS map2_subject
ON map2_subject.subject_id = map2.subject_id
Result:
And if you want to list the students that have just one subject as well, you'll need to make a UNION, because just removing the <> will make it impossible to calculate the actual number of students in just one subject:
;WITH subjects AS
(
SELECT 1 AS subject_id, 'Biology' AS subject_name
UNION ALL SELECT 2 AS subject_id, 'Chemistry' AS subject_name
UNION ALL SELECT 3 AS subject_id, 'Physics' AS subject_name
)
,students AS
(
SELECT 1 AS student_id, 'Student A' AS student_name
UNION ALL SELECT 2 AS student_id, 'Student B' AS student_name
UNION ALL SELECT 3 AS student_id, 'Student C' AS student_name
UNION ALL SELECT 4 AS student_id, 'Student D' AS student_name
)
,map_student_subject AS
(
SELECT 1 AS student_id, 1 AS subject_id
UNION ALL SELECT 1 AS student_id, 2 AS subject_id
UNION ALL SELECT 2 AS student_id, 2 AS subject_id
UNION ALL SELECT 2 AS student_id, 3 AS subject_id
UNION ALL SELECT 3 AS student_id, 3 AS subject_id
UNION ALL SELECT 4 AS student_id, 3 AS subject_id
)
SELECT
map1.student_id AS map1_student_id
,map1_student.student_name AS map1_student_name
,map1.subject_id AS map1_subject_id
,map1_subject.subject_name AS map1_subject_name
,map2.student_id AS map2_student_id
,map2_student.student_name AS map2_student_name
,map2.subject_id AS map2_subject_id
,map2_subject.subject_name AS map2_subject_name
FROM map_student_subject AS map1
INNER JOIN map_student_subject AS map2
ON map2.student_id = map1.student_id
AND map2.subject_id <> map1.subject_id
LEFT JOIN students AS map1_student
ON map1_student.student_id = map1.student_id
LEFT JOIN students AS map2_student
ON map2_student.student_id = map2.student_id
LEFT JOIN subjects AS map1_subject
ON map1_subject.subject_id = map1.subject_id
LEFT JOIN subjects AS map2_subject
ON map2_subject.subject_id = map2.subject_id
UNION ALL
SELECT
students.student_id AS map1_student_id
,students.student_name AS map1_student_name
,MAX(subjects.subject_id) AS map1_subject_id
,MAX(subjects.subject_name) AS map1_subject_name
,students.student_id AS map2_student_id
,students.student_name AS map2_student_name
,MAX(subjects.subject_id) AS map2_subject_id
,MAX(subjects.subject_name) AS map2_subject_name
FROM map_student_subject
LEFT JOIN students ON students.student_id = map_student_subject.student_id
LEFT JOIN subjects ON subjects.subject_id = map_student_subject.subject_id
GROUP BY
students.student_id
,students.student_name
HAVING COUNT(*) = 1

Multiple rows with 2 condition in the same column MySQL

How to select multiple rows with 2 condition in the same column MySQL
students' table:
id name
1 Jhon
2 Anne
3 Charles
4 Bob
lesson_contract's table:
id lesson_code student_id
1 L1 1
2 L2 1
3 L1 2
4 L1 3
5 L2 3
6 L2 4
So i want to get student that take both lesson_code L1 and L2. So the result should be Jhon and Charles
You could do this by joining into the lesson_contract table twice, once for each lesson code:
SELECT s.id, s.name FROM students s
INNER JOIN lesson_contract l1
ON s.id = l1.student_id AND l1.lesson_code = 'L1'
INNER JOIN lesson_contract l2
ON s.id = l2.student_id AND l2.lesson_code = 'L2'
Inner joins will filter the results, so you'll only get rows where both join conditions were met.
You must join the tables, group by name and put the condition in the having clause:
select s.name
from student s inner join lesson_contract l
on l.student_id = s.id
where l.lesson_code in ('L1', 'L2')
group by s.name
having count(distinct l.lesson_code) = 2
You may remove distinct if there is no case for a student to take the same lesson twice.
See the demo.
Results:
| name |
| ------- |
| Charles |
| John |

How to write a query for selecting from three tables and if the values are null should not select?

I have three tables
1) Category_master
CID CTYPE
---------------------
1 2
--------------------
2 2
--------------------
3 1
-------------------
4 3
----------------
5 2
-------------------
6 3
2) NSS_maste
NID MID Name Value
1 5 Red 86
2 1 Blue 96
3) Sports_master
SID MID Name Cat
1 4 Walk Leg
The above is my table
I have to select CTYPE, NSS.NAME NSS.value,sports.name, sports.cat from category master,NSS_master and sports_master an it should not select null value Eg: for CID 2 there is no value in NSS_master table so it should not select but for CID 3 CTYPE 1 select name and other values as null
How to implement this thank you
Use Inner Join to avoid null values:
SELECT C.CTYPE, N.NAME, N.value, S.name, S.cat
FROM Category_Master C Inner Join NSS_master N ON C.CID = N.MID
Inner Join Sports_Master S ON C.CID = S.MID

Selecting data based on other table

I'm still newbie with database and mysql stuff, i want to learn how to use JOINs.I'm sorry i just have no idea to put this case on words. I hope all of You can understand by looking these data. Here's the tables with records:
Table student
student_id | student_name
-------------------------
1 Ana
2 Billy
3 Connor
Table comp
comp_id | subj_id | comp_name
--------------------------
1 24 Run
2 24 Swim
3 24 Jump
4 25 Eat
Table comp_mark
semester | subj_id | student_id | comp_id | mark
-------------------------------------------------
1 24 1 1 7
1 24 1 2 4
1 24 1 3 6
1 24 2 1 4
1 24 2 2 8
1 24 3 1 9
I'm expecting the result something like this from the query selecting comp_mark table(update):
student_name | semester | subject_id | comp_id | mark
-------------------------------------------------------
Connor 1 24 1 9
Connor null 24 2 null
Connor null 24 3 null
is there anyone can help me with this? Thank a ton
UPDATE
I've tried this (Guillaume Poussel's query) and ORDER it by student_name :
SELECT s.student_name, cm.semester, c.subj_id AS subject_id, c.comp_id, cm.mark
FROM student s
CROSS JOIN comp c
LEFT JOIN comp_mark cm ON s.student_id = cm.student_id
AND cm.subj_id = c.subj_id
AND cm.comp_id = c.comp_id
ORDER BY s.student_name
The results:
Try this one:
SELECT s.student_name, cm.semester, c.subj_id AS subject_id, c.comp_id, cm.mark
FROM student s
CROSS JOIN comp c
LEFT JOIN comp_mark cm ON s.student_id = cm.student_id AND cm.subj_id = c.subj_id AND cm.comp_id = c.comp_id
Think you need to add a cross join to get all the possible values from comp. Something like this:-
SELECT s.student_name, c.subj_id, s.student_id, c.comp_id, cm.mark
FROM student s
CROSS JOIN comp c
LEFT OUTER JOIN comp_mark cm
ON s.student_id = cm.student_id
AND cm.semester = '1'
AND cm.subj_id = '1'