Joint 3 table mysql error [duplicate] - mysql

I have three tables named
**Student Table**
-------------
id name
-------------
1 ali
2 ahmed
3 john
4 king
**Course Table**
-------------
id name
-------------
1 physic
2 maths
3 computer
4 chemistry
**Bridge**
-------------
sid cid
-------------
1 1
1 2
1 3
1 4
2 1
2 2
3 3
3 4
4 1
4 2
Now to show the student name with the course name which he had studied like,
**Result**
---------------------------
Student Course
---------------------------
ahmed physic
ahmed maths
ahmed computer
ahmed chemistry
ali physic
ali maths
john computer
john chemistry
king physic
king maths
I build following query
select s.name as Student, c.name as Course from student s, course c join bridge b on c.id = b.cid order by s.name
But it does not return the required result...
And what would be for normalized form, if I want to find who is manager over other:
**employee**
-------------------
id name
-------------------
1 ali
2 king
3 mak
4 sam
5 jon
**manage**
--------------
mid eid
--------------
1 2
1 3
3 4
4 5
And wants to get this result:
**result**
--------------------
Manager Staff
--------------------
ali king
ali mak
mak sam
sam jon

Use ANSI syntax and it will be a lot more clear how you are joining the tables:
SELECT s.name as Student, c.name as Course
FROM student s
INNER JOIN bridge b ON s.id = b.sid
INNER JOIN course c ON b.cid = c.id
ORDER BY s.name

Simply use:
select s.name "Student", c.name "Course"
from student s, bridge b, course c
where b.sid = s.sid and b.cid = c.cid

For normalize form
select e1.name as 'Manager', e2.name as 'Staff'
from employee e1
left join manage m on m.mid = e1.id
left join employee e2 on m.eid = e2.id

SELECT *
FROM user u
JOIN user_clockits uc ON u.user_id=uc.user_id
JOIN clockits cl ON cl.clockits_id=uc.clockits_id
WHERE user_id = 158

Don't join like that. It's a really really bad practice!!! It will slow down the performance in fetching with massive data. For example, if there were 100 rows in each tables, database server have to fetch 100x100x100 = 1000000 times. It had to fetch for 1 million times. To overcome that problem, join the first two table that can fetch result in minimum possible matching(It's up to your database schema). Use that result in Subquery and then join it with the third table and fetch it. For the very first join --> 100x100= 10000 times and suppose we get 5 matching result. And then we join the third table with the result --> 5x100 = 500. Total fetch = 10000+500 = 10500 times only. And thus, the performance went up!!!

join query with three tables and we want two values from the same column we set the alias name for every table in the joins. Same table name also declare as a different names.
const sql = `select p.ID,p.purchaseamount,urs.name as
buyername,pd.productname,
pd.amount,urs1.name as sellername
from purchases p
left join products pd on p.productid=pd.ID
left join users urs on p.userid=urs.ID
left join users urs1 on pd.userid=urs1.ID`

SELECT
employees.id,
CONCAT(employees.f_name," ",employees.l_name) AS 'Full Name', genders.gender_name AS 'Sex',
depts.dept_name AS 'Team Name',
pay_grades.pay_grade_name AS 'Band',
designations.designation_name AS 'Role'
FROM employees
LEFT JOIN genders ON employees.gender_id = genders.id
LEFT JOIN depts ON employees.dept_id = depts.id
LEFT JOIN pay_grades ON employees.pay_grade_id = pay_grades.id
LEFT JOIN designations ON employees.designation_id = designations.id
ORDER BY employees.id;
You can JOIN multiple TABLES like this example above.

Just adding a point to previous answers that in MySQL we can either use
table_factor syntax
OR
joined_table syntax
mysql documentation
Table_factor example
SELECT prd.name, b.name
FROM products prd, buyers b
Joined Table example
SELECT prd.name, b.name
FROM products prd
left join buyers b on b.bid = prd.bid;
FYI: Please ignore the fact the the left join on the joined table example doesnot make much sense (in reality we would use some sort of join table to link buyer to the product table instead of saving buyerID in product table).

Query for three table join and limit set
SELECT * FROM (SELECT t1.follower_userid, t2.*, t3.login_thumb, t3.login_name,
t3.bio, t3.account_status, t3.gender
FROM videos t2
LEFT JOIN follower t1
ON t1.follower_userid = t2.user_id
LEFT JOIN videos_user t3
ON t1.follower_userid = t3.login_userid
WHERE t1.following_userid='$userid'
LIMIT $startpoint , $limit) AS ID
ORDER BY ID DESC

Query to join more than two tables:
SELECT ops.field_id, ops.option_id, ops.label
FROM engine4_user_fields_maps AS map
JOIN engine4_user_fields_meta AS meta ON map.`child_id` = meta.field_id
JOIN engine4_user_fields_options AS ops ON map.child_id = ops.field_id
WHERE map.option_id =39 AND meta.type LIKE 'outcomeresult' LIMIT 0 , 30

Use this:
SELECT s.name AS Student, c.name AS Course
FROM student s
LEFT JOIN (bridge b CROSS JOIN course c)
ON (s.id = b.sid AND b.cid = c.id);

Related

MySQL - query that should filter based on records contained in the join table [duplicate]

This question already has answers here:
Left Outer Join doesn't return all rows from my left table?
(3 answers)
Closed 6 months ago.
studentTable:
id
studentName
1
Name1
2
Name2
3
Name3
studentCourseTable:
id
studentId
courseId
1
1
1
2
1
2
3
3
1
4
3
3
5
2
2
I want to (let's say) list students who have taken courseId 1 AND 3 (together) BUT have NOT taken 2. Or any dynamic combination such as that, like courseId 1,2,3 should be taken; 1,2 not taken but 3 is taken etc etc.
I have tried some JOIN clause to filter but have not been able to apply more than 1 condition:
SELECT student.*
FROM studentTable AS s
LEFT JOIN studentCourseTable AS sc
ON sc.studentId = s.id
WHERE sc.studentId IN (1,3)
AND sc.studentId NOT IN (2)
or:
SELECT student.*
FROM studentTable AS s
LEFT JOIN studentCourseTable AS sc
ON sc.studentId = s.id
AND sc.courseId IN (1, 3)
AND sc.courseId IN (2)
The important thing is that I want to find students that take specified courses TOGETHER, AND not take any other specified course. The student may take more courses than specified (as long as it is not in NOT taken list).
**Edit for some clarifications: ** For example if I say the student should take (2,4) but NOT (3), returning a student that takes (2,4,5) is ok. But (2,3) or (2,4,5) are NOT ok.
There are some other tables that I'm joining the student table with, not sure if it matters but this is the gist of it.
Can anyone assist me with this?
** Edit: ** #lemon has cracked it. Here's the demo he made, which lists any user that attended 1 OR 3 AND have not attended 2. Here's my updated demo which lists students that attended 1 AND 3 AND have not attended 2.
Thanks to all who helped me, this was superb.
You can select all information from your students and use two kind of JOIN operations:
an INNER JOIN for each due attended course
a LEFT JOIN for non-attended courses, to be filtered out in the WHERE clause
SELECT s.*
FROM students s
INNER JOIN (SELECT DISTINCT studentId FROM courses WHERE courseId = 1) c1
ON s.id = c1.studentId
INNER JOIN (SELECT DISTINCT studentId FROM courses WHERE courseId = 3) c3
ON s.id = c3.studentId
LEFT JOIN (SELECT DISTINCT studentId FROM courses WHERE courseId IN (2)) not_c
ON s.id = not_c.studentId
WHERE not_c.studentId IS NULL
Check the demo here.
Another option is to count
positively your needed courses
negatively your unneeded courses
Eventually sum up the values, and filter out those students whom don't have sum equal to the amount of needed courses.
SELECT s.*
FROM courses c
INNER JOIN students s
ON s.id = c.studentId
GROUP BY s.id,
s.studentName
HAVING SUM(CASE WHEN c.courseId IN (1,3) THEN 1
WHEN c.courseId IN (2) THEN -1 END) = 2
Check the demo here.
To get only students that are in groups 1 and 3
SELECT s.studentName
from studenttable AS s
INNER JOIN studentCourseTable AS sc ON sc.studentId = s.id
where sc.courseId in (1,3)
group by s.id
having count(*) = 2;
We first should group by student name or id, then we get only those that are in the 2 courses by adding "having count(*) = 2"

How to get name and surname from two id linked to same table SQL

I have i question about JOINign i have tables User and Category and Request
Id
name
surname
1
Alex
Morgan
2
Tom
Brady
3
Smith
Rowe
Category
Id
Category
1
Party
2
Football match
And now someone create request for another
Request
Id_request
Id_caller
Id_receiver
id_category
1
1
2
1
2
1
3
2
Now i want query to find all request where user 1 (Alex) is caller and get this result
Id_request
Caller_name
Caller_surname
Receiver_name
Receiver _surname
Category
1
Alex
Morgan
Tom
Brady
Party
2
Alex
Morgan
Smith
Rowe
Football match
I try with JOIN but i didn't get this result. Pls help.
You just need to join the tables and take the necessary columns.
However, you need to join the table user twice. When joining a table twice, at least one of them needs to have an alias. The query shown below uses aliases for all tables.
For example, you can do:
select
q.id_request,
c.name as caller_name,
c.surname as caller_surname,
r.name as receiver_name,
r.surname as receiver_surname,
c.category
from request q
join user c on c.id = q.id_caller
join user r on r.id = q.id_receiver -- joined user again with different alias
join category y on y.id = q.id_category
where q.id_caller = 1
You just need two joins, one for the caller and another for the receiver.
select
id_request,
uc.nm_user as "Caller_name",
uc.nm_surname as "Caller_surname",
rr.nm_user as "Receiver_name",
rr.nm_surname as "Receiver_surname",
c.nm_category
from
usr uc
join
request rc on rc.id_caller = uc.id_user
join
usr rr on rr.id_user = rc.id_receiver
join
category c on c.id_category = rc.id_category
where
uc.id_user = 1
Here is the complete example
https://www.db-fiddle.com/f/cA637bx33SFMeDtyUUNqsp/0
You need to join the User table twice with request table -
SELECT R.Id_request,
U1.Caller_name,
U1.Caller_surname,
U2.Receiver_name,
U2.Receiver_surname,
C.Category
FROM Request R
JOIN User U1 ON R.Id_caller = U1.Id
JOIN User U2 ON R.Id_receiver = U2.Id
JOIN Category C ON r.id_category = C.Id;

What SQL query should I use to get information from database? [duplicate]

I have three tables named
**Student Table**
-------------
id name
-------------
1 ali
2 ahmed
3 john
4 king
**Course Table**
-------------
id name
-------------
1 physic
2 maths
3 computer
4 chemistry
**Bridge**
-------------
sid cid
-------------
1 1
1 2
1 3
1 4
2 1
2 2
3 3
3 4
4 1
4 2
Now to show the student name with the course name which he had studied like,
**Result**
---------------------------
Student Course
---------------------------
ahmed physic
ahmed maths
ahmed computer
ahmed chemistry
ali physic
ali maths
john computer
john chemistry
king physic
king maths
I build following query
select s.name as Student, c.name as Course from student s, course c join bridge b on c.id = b.cid order by s.name
But it does not return the required result...
And what would be for normalized form, if I want to find who is manager over other:
**employee**
-------------------
id name
-------------------
1 ali
2 king
3 mak
4 sam
5 jon
**manage**
--------------
mid eid
--------------
1 2
1 3
3 4
4 5
And wants to get this result:
**result**
--------------------
Manager Staff
--------------------
ali king
ali mak
mak sam
sam jon
Use ANSI syntax and it will be a lot more clear how you are joining the tables:
SELECT s.name as Student, c.name as Course
FROM student s
INNER JOIN bridge b ON s.id = b.sid
INNER JOIN course c ON b.cid = c.id
ORDER BY s.name
Simply use:
select s.name "Student", c.name "Course"
from student s, bridge b, course c
where b.sid = s.sid and b.cid = c.cid
For normalize form
select e1.name as 'Manager', e2.name as 'Staff'
from employee e1
left join manage m on m.mid = e1.id
left join employee e2 on m.eid = e2.id
SELECT *
FROM user u
JOIN user_clockits uc ON u.user_id=uc.user_id
JOIN clockits cl ON cl.clockits_id=uc.clockits_id
WHERE user_id = 158
Don't join like that. It's a really really bad practice!!! It will slow down the performance in fetching with massive data. For example, if there were 100 rows in each tables, database server have to fetch 100x100x100 = 1000000 times. It had to fetch for 1 million times. To overcome that problem, join the first two table that can fetch result in minimum possible matching(It's up to your database schema). Use that result in Subquery and then join it with the third table and fetch it. For the very first join --> 100x100= 10000 times and suppose we get 5 matching result. And then we join the third table with the result --> 5x100 = 500. Total fetch = 10000+500 = 10500 times only. And thus, the performance went up!!!
join query with three tables and we want two values from the same column we set the alias name for every table in the joins. Same table name also declare as a different names.
const sql = `select p.ID,p.purchaseamount,urs.name as
buyername,pd.productname,
pd.amount,urs1.name as sellername
from purchases p
left join products pd on p.productid=pd.ID
left join users urs on p.userid=urs.ID
left join users urs1 on pd.userid=urs1.ID`
SELECT
employees.id,
CONCAT(employees.f_name," ",employees.l_name) AS 'Full Name', genders.gender_name AS 'Sex',
depts.dept_name AS 'Team Name',
pay_grades.pay_grade_name AS 'Band',
designations.designation_name AS 'Role'
FROM employees
LEFT JOIN genders ON employees.gender_id = genders.id
LEFT JOIN depts ON employees.dept_id = depts.id
LEFT JOIN pay_grades ON employees.pay_grade_id = pay_grades.id
LEFT JOIN designations ON employees.designation_id = designations.id
ORDER BY employees.id;
You can JOIN multiple TABLES like this example above.
Just adding a point to previous answers that in MySQL we can either use
table_factor syntax
OR
joined_table syntax
mysql documentation
Table_factor example
SELECT prd.name, b.name
FROM products prd, buyers b
Joined Table example
SELECT prd.name, b.name
FROM products prd
left join buyers b on b.bid = prd.bid;
FYI: Please ignore the fact the the left join on the joined table example doesnot make much sense (in reality we would use some sort of join table to link buyer to the product table instead of saving buyerID in product table).
Query for three table join and limit set
SELECT * FROM (SELECT t1.follower_userid, t2.*, t3.login_thumb, t3.login_name,
t3.bio, t3.account_status, t3.gender
FROM videos t2
LEFT JOIN follower t1
ON t1.follower_userid = t2.user_id
LEFT JOIN videos_user t3
ON t1.follower_userid = t3.login_userid
WHERE t1.following_userid='$userid'
LIMIT $startpoint , $limit) AS ID
ORDER BY ID DESC
Query to join more than two tables:
SELECT ops.field_id, ops.option_id, ops.label
FROM engine4_user_fields_maps AS map
JOIN engine4_user_fields_meta AS meta ON map.`child_id` = meta.field_id
JOIN engine4_user_fields_options AS ops ON map.child_id = ops.field_id
WHERE map.option_id =39 AND meta.type LIKE 'outcomeresult' LIMIT 0 , 30
Use this:
SELECT s.name AS Student, c.name AS Course
FROM student s
LEFT JOIN (bridge b CROSS JOIN course c)
ON (s.id = b.sid AND b.cid = c.id);

Mysql getting all subject with student name even if id is not there

I have below database structure:
students table
id name gender
1 abc male
2 xyz female
subjects table
id name
1 maths
2 science
3 english
studentmarks
id st_id sub_id marks
1 1 1 20
2 1 2 30
3 2 1 40
I want result like this:
name subjects marks
abc maths 20
abc science 30
xyz maths 40
abc english 0
xyz science 0
xyz english 0
Is it possible to achieve above result with MySQL query alone?
I tried this query:
SELECT *
FROM students
LEFT JOIN studentmarks
ON studentmarks.std_id = students.id
LEFT JOIN subjects
ON subjects.id = studentmarks.sub_id
The result is not as I want, because I am using join so it will only return the matching id.
This may work
SELECT cr.st_name, cr.sub_name, COALESCE(c.marks, 0)
FROM (SELECT a.id st_id,
a.NAME st_name,
b.NAME sub_name,
b.id sub_id
FROM students a,
subjects b) cr
LEFT JOIN studentmarks c
ON cr.sub_id = c.sub_id
AND c.st_id = cr.st_id
Try that one
SELECT A.name, B.name, C.marks
FROM students A, subjects B, studentmarks C
WHERE A.id = C.st_id AND B.id = C.sub_id;
You can achieve the result using following query
SELECT SM.marks,
S.NAME AS Student_name,
SBJ.NAME as Subject
FROM studentmarks AS SM
JOIN students AS S ON SM.st_id = S.id
JOIN subjects AS SBJ ON SM.sub_id = SBJ.id
You can also use CROSS join as well I guess if you want to stick with your current query

Mysql Table Structure Working Fast?

I am planning to create a website similar to IMDB.com. To reduce execution time I am using the following structure. Is it okay for faster working?
Table - 1
Id Movie_name description
1 name one some description
2 name two some description
3 name three some description
Table 2
id actorname
1 name 1
2 name 2
3 name 3
4 name 4
Table 3
id movieid actorid
1 1 1
2 1 2
3 1 3
4 1 9
5 2 6
6 2 5
7 2 8
8 2 1
When I want to list actors in a movie program will retrieve actors ids from table 3 and find respective names from table 2 (using single query). When I want to list the movies of a actor it will retrieve movie ids from table 3 and find respective names from first table. Will it work properly? Any other ideas?
This will give all actors in a specified movie,
SELECT c.ID, c.actorName
FROM table1 a
INNER JOIN table3 b
ON a.ID = b.movieID
INNER JOIN table2 c
ON b.actorid = c.ID
WHERE a.ID = 1
This one will give all movies for a specified actor
SELECT a.*
FROM table1 a
INNER JOIN table3 b
ON a.ID = b.movieID
INNER JOIN table2 c
ON b.actorid = c.ID
WHERE c.ID = 1
SQLFiddle Demo (both queries)
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
UPDATE 1
This is called Relational Division
SELECT a.ID, a.Movie_Name
FROM table1 a
INNER JOIN table3 b
ON a.ID = b.movieID
INNER JOIN table2 c
ON b.actorid = c.ID
WHERE c.ID IN (1, 2, 3)
GROUP BY a.ID, a.Movie_Name
HAVING COUNT(DISTINCT c.ID) = 3
SQL of Relational Division
I suggest that you modify table3 by taking away the id field. Use the movieid and actorid together as your primary key. You might want to add other fields to this table such as name of character and order of appearance as suggested in the comment by Jermaine Xu.