I have two tables that references each other via id. I want to connect a given name in the first table, to a relation with one or many persons using a second table. See example
Person
id
name
Adress
1
Jonas
Sturmwind Street 12 5431
2
Thomas
New Banksy Home 14 5432
3
Therese
Redcarpet Willow 1 6623
4
Nicko
Redcarpet Willow 1 6623
5
Sandra
Mcmurdo Station
Related
related_from_id
related_to_id
Relation
1
2
"Sibling"
1
5
"Sibling"
3
4
"Parent"
Given a name, how can I make a mysql query that gives me any potential siblings name and adress.
For instance I query with param "Jonas" and expect the result set to be
Relation
Name
Related to
Adress
Jonas
"Thomas"
"New Banksy Home 14 5432"
"Sandra"
"Mcmurdo Station"
In order to have your result
SELECT
p.name AS NAME,
p1.name AS relatedTo,
p1.Address
FROM
Person p,
Related r,
Person p1
WHERE r.related_from_id = p.id
AND r.related_to_id = p1.id
AND p.name = 'Jonas' ;
However, if the relationship is in any direction, #The Impater's answer has you covered.
I would assume you want to walk the related table in any direction (left-right or right-left).
You can do:
select p.name, o.name as related_to, o.address
from person p
join related r on p.id in (r.related_from_id, r.related_to_id)
join person o on r.related_from_id = p.id and o.id = related_to_id
or r.related_to_id = p.id and o.id = related_from_id
where p.name = 'Jonas'
Related
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;
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);
i've experienced something... weird? using an aggregate function WITHOUT group by statement (yes, i know i sould). I'm using mysql 5.5 in this moment.
I've use some example tables with the same structure as in my real situation, so example may be extrange, sorry.
Let's explain.
I have three tables with some referencial integrity:
As you can imagine: both, parent, child and person, are FK from Persons table id.
- Persons -
id name
1 Anna
2 Ben
3 Charly
4 Dennis
5 Emma
6 Fiona
- Relationships -
parent child
1 3
1 4
2 5
- Log -
person date
1 2020-05-05
Anna has two childs, Charly and Dennis
Ben has one, Emma
Fiona hasn't
Only Anna has an entry on log table
Let's party.
Find children id 3 name ONLY if number 6 is his parent (looking for Charly if is Fiona's son)
select P.name, R.child, R.parent
from Persons P
join Relationships R on P.id = R.child
left join Log L on L.person = P.id
where R.parent = 1
and R.child = 3
No result shown, ok, that's what i expected because as we can see, there's no row that matches condition.
Adding an aggregate function and group by shows the same 0 results.
select P.name, R.child, R.parent, count(L.person) as N_Entries
from Persons P
join Relationships R on P.id = R.child
left join Log on L.person = P.id
where R.parent = 1
and R.child = 3
group by P.id
BUT
if i remove the group by condition i expect the same result
if there're no result, then grouping should be unnecesary.
select P.name, R.child, R.parent, count(L.person) as N_Entries
from Persons P
join Relationships R on P.id = R.child
left join Log on L.person = P.id
where R.parent = 1
and R.child = 3
name child parent N_Entries
Charly null null 0
Why does it returns something?
Thank you and sorry about my bad english.
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);
So i have this relational model for hospital (not made by me).
Patient (has an adress and an id), hospital (has id and address), and also there's a table for relationship representing placement in the hospital (hospital.id, patient.id) (also there's other tables, but they don't matter in this query);
The purpose of the query is to find hospitals where is no placed patients from from other cities than hospital's one (on condition that address only contains city).
The problem that i have is theoretical, i don't really know if to use full outer join with a or b null, or something else in the query that finds hospitals containing "foreign" patients, (like join hospital with its placement and then full outer join with a or b table record null, but that leads to a question will i get results in the query? Because i need cities that don't match but all the explanations of that join are about .
Thanks to all who embraced my utterly imperfect english and understood it.
Upd.
Patient:
id=1, city =A;
id=2, city =B;
id=3, city =B;
id=4, city =A;
id=5, city =C;
Hospital:
Id =1, city=A
id =2, city=B;
Placement:
h.id p.id
1 1
1 4
2 2
2 3
2 5
Expected results is "1", id of the first hospital (where's no patients from other city) and others with that "feature"
my query is like
select id from hospital where id not in
(select id,address from hospital inner join placement on h.id=placement.h.id as b inner join patient on placement.p.id=p.id where hospital.address<>patient.address )
Sorry for the delay
Is shawn's query correct?
Can i use h.id instead 1? Idk if our teacher would accept that, because he's never showed us something like that and in 10 years he hasn't managed to create an example of that database for students to test queries on.
select * from hospitals h
where not exists (
select 1 -- dummy value, use h.id if you prefer
from patients p inner join placement pl on pl.pid = p.id
where pl.hid = h.id and p.city <> h.city
)
or
select h.id
from hospitals h
left outer join
placement pl inner join patients p on p.id = pl.pid
on pl.hid = h.id
group by h.id
-- this won't count nulls resulting from zero placements for that hospital
-- as long as standard sql null comparisons are active
having count(case when h.city <> p.city then 1 end) = 0
Looks like it works to me: http://rextester.com/BTJB59061