user1492385
user1492385

Reputation: 105

MySQL - Multiple Union

(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

Answers (2)

Kao
Kao

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

Muhammad Raheel
Muhammad Raheel

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

Related Questions