Reputation: 105
(Bonus internets for anyone who can explain how I can do this in both SQL and SQLAlchemy.)
I have three tables set up like so:
**Bottom:**
id
name
middle_id
**Middle:**
id
name
top_id
**Top:**
id
name
Each bottom has a middle, and each middle has a top. I want to do a search on a database so that when the user types in their query, it will search Bottom, Middle, and Top. If someone searches for an item that happens to be in Top, it will return all the Bottom.* that are related to Top by going through Middle.
Here's a query that works on two levels:
SELECT *
FROM Bottom
WHERE name LIKE '%query%'
UNION
SELECT Bottom.*
FROM Middle JOIN Bottom ON Bottom.middle_id = Middle.id
WHERE Middle.name LIKE '%query%'
How do I extend this so that it can also search Top WHERE Top.name LIKE '%query%', but instead of returning Middle.*, it returns Bottom.*? Here's some SQL that doesn't work, but I think explains what I'm trying to achieve:
SELECT *
FROM Bottom
WHERE name LIKE '%query%'
UNION
SELECT Bottom.*
FROM Middle JOIN Bottom ON Bottom.middle_id = Middle.id
WHERE Middle.name LIKE '%query%'
UNION
SELECT Bottom.*
FROM Top JOIN Middle ON Middle.top_id = Top.id
WHERE Top.name LIKE '%query%'
In other words, if I have an entry in Bottom that is related to an entry in Middle, and that entry in Middle is related to an entry in Top, if I search Top for the appropriate name, it will return not the Middle entry that is related to it, but the Bottom entry that is related to the related Middle entry.
Here is an example:
Data:
**Bottom**
id 1
name Gus Fring
middle_id 1
**Middle**
id 1
name Jesse Pinkman
top_id 1
**Top**
id 1
name Walter White
If I search for "Walter White" it will return not the Middle relation (Jesse Pinkman), but rather the Bottom relation's to the Middle relation's result (Gus Fring).
This issue has been troubling me for a while now and I'd really appreciate any help. Thanks in advance! :)
Upvotes: 0
Views: 1992
Reputation: 2272
I think you should use LEFT JOINS. What you do is join all the tables, and then search for the values.
Let me provide you with some code:
SELECT
bottom.name,
middle.name,
top.name
FROM
bottom
LEFT JOIN middle ON top.id = middle.id
LEFT JOIN top ON middle.id = top.id
WHERE
middle.name LIKE '%name%'
OR top.name LIKE '%name%'
OR bottom.name LIKE '%name%'
Upvotes: 3
Reputation: 19882
Try this
select
b.id,
b.name,
b.middle_id,
m.top_id,
m.name,
t.name
from bottom as b
left join (select id,`name`, top_id from Middle) as m on m.id = b.middle_id
left join (select id,`name`from Top) as t on t.id = m.top_id
Upvotes: 2