Question : mySQL complicated unions and subqueries

Once again, my mind is boggled by the need to process multiple "alternatives" using unions. It all comes from a faulty database structure, I"m sure, but that's not negotiable at this time.

Essentially imagine two parallel structures within the same DB - for each table, there are also arc_ (archive) versions of that table for the older records, to optimize searches on the more current records. Anyhoo, this is neither here nor there - the issue is now writing queries against BOTH sets.

I need an answer instantly, so I am just going to write this out here, in the hopes that just writing out the question gives me a clue to the answer and, well, if some Expert genius out there (AngelIII, I'm looking at YOU!) sees this in time, well bonus!

Oh, and I _need_ to do this in a single mySQL query, even though I'm writing it out in logical "steps", the way the optimizer ought to approach solving the record set.

1. find all messages where title = 'hello' OR all arc_messages where title = 'hello' (union)
2. for any message, join on `recipient`; for any arc_message, join on `arc_recipient`
3. get the ID from the `recipient` or `arc_recipient` record. This ID is a foreign key to EITHER `student` OR `arc_student`, but we don't know which.
4. using this ID, join on `student` OR `arc_student` and give me the name

So:

message -> notification -> student OR arc_student
arc_message -> arc_notification -> student OR arc_student

It feels like I want something like:
select M.*, S.name
from
(
  select message.*, notification.*
  from message
  join notification on message.notification_id = notification.row_id
  where message.title = 'hello'

  union

  select arc_message.*, arc_notification.*
  from arc_message
  join arc_notification on arc_message.notification_id = arc_notification.row_id
  where arc_message.title = 'hello'
) as M

join (
  select student.name
  from student
  where student.row_id = M.student_id <-- unknown column M.student_id

  union

  select arc_student.name
  from arc_student
  where arc_student.row_id = M.student.id <-- unknown column M.student_id
) as S


but of course M is out of scope inside this join.

My point is, I don't want to have to left join student, arc_student outside, because then I'm left with two tables that I'm constantly going to have to ifnull(student.name, arc_student.name) as studentName etc.... and while it seems pretty trivial in this simplified example, it's going to get messy in the real (bigger) query.

Is there truly no way to make the result (student_id) from the first subquery (the message / arc_message union) in scope for the student / arc_student join?

It would be simple if there was a correlation between arc_message -> arc_student and message -> student, but unfortunately that's just not the case.

I could put the student / arc_student union as another subselect inside message / arc_message, but then I would have to do it twice, wouldn't I? Once for message and once for arc_message, and that just seems like it would be redundant and generate a Cartesian cross product.

Hmmm, maybe the inner subselect isn't a bad idea....

Answer : mySQL complicated unions and subqueries

The catch is that if a student (row_id) appears in both student and arc_student BUT WITH DIFFERENT NAME... well, you're going to get a cross product.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
select M.*, S.name
from
(
  select message.*, notification.*
  from message
  join notification on message.notification_id = notification.row_id
  where message.title = 'hello'
union
  select arc_message.*, arc_notification.*
  from arc_message
  join arc_notification on arc_message.notification_id = arc_notification.row_id
  where arc_message.title = 'hello'
) as M
join (
  select student.row_id, student.name
  from student
union
  select arc_student.row_id, arc_student.name
  from arc_student
) as S ON M.student_id = S.row_id
Random Solutions  
 
programming4us programming4us