MySQL LEFT OUTER JOIN virtual table
Posted
by
user1707323
on Stack Overflow
See other posts from Stack Overflow
or by user1707323
Published on 2012-11-13T16:45:29Z
Indexed on
2012/11/13
17:00 UTC
Read the original article
Hit count: 234
I am working on a pretty complicated query let me try to explain it to you. Here is the tables that I have in my MySQL database:
students Table
--- `students` ---
student_id first_name last_name current_status status_change_date
------------ ------------ ----------- ---------------- --------------------
1 John Doe Active NULL
2 Jane Doe Retread 2012-02-01
students_have_courses Table
--- `students_have_courses` ---
students_student_id courses_course_id s_date e_date int_date
--------------------- ------------------- ---------- ---------- -----------
1 1 2012-01-01 2012-01-04 2012-01-05
1 2 2012-01-05 NULL NULL
2 1 2012-01-10 2012-01-11 NULL
students_have_optional_courses Table
--- `students_have_optional_courses` ---
students_student_id optional_courses_opcourse_id s_date e_date
--------------------- ------------------------------ ---------- ----------
1 1 2012-01-02 2012-01-03
1 1 2012-01-06 NULL
1 5 2012-01-07 NULL
Here is my query so far
SELECT
`students_and_courses`.student_id,
`students_and_courses`.first_name,
`students_and_courses`.last_name,
`students_and_courses`.courses_course_id,
`students_and_courses`.s_date,
`students_and_courses`.e_date,
`students_and_courses`.int_date,
`students_have_optional_courses`.optional_courses_opcourse_id,
`students_have_optional_courses`.s_date,
`students_have_optional_courses`.e_date
FROM (
SELECT
`c_s_a_s`.student_id,
`c_s_a_s`.first_name,
`c_s_a_s`.last_name,
`c_s_a_s`.courses_course_id,
`c_s_a_s`.s_date,
`c_s_a_s`.e_date,
`c_s_a_s`.int_date
FROM (
SELECT
`students`.student_id,
`students`.first_name,
`students`.last_name,
`students_have_courses`.courses_course_id,
`students_have_courses`.s_date,
`students_have_courses`.e_date,
`students_have_courses`.int_date
FROM
`students`
LEFT OUTER JOIN `students_have_courses`
ON (
`students_have_courses`.`students_student_id` = `students`.`student_id` AND ((
`students_have_courses`.`s_date` >= `students`.`status_change_date` AND
`students`.current_status = 'Retread' ) OR
`students`.current_status = 'Active')
)
WHERE
`students`.current_status = 'Active' OR
`students`.current_status = 'Retread'
) `c_s_a_s`
ORDER BY
`c_s_a_s`.`courses_course_id` DESC
) `students_and_courses`
LEFT OUTER JOIN `students_have_optional_courses`
ON (
`students_have_optional_courses`.students_student_id = `students_and_courses`.student_id AND
`students_have_optional_courses`.s_date >= `students_and_courses`.s_date AND
`students_have_optional_courses`.e_date IS NULL
)
GROUP BY
`students_and_courses`.student_id;
What I want to be returned is the student_id, first_name, and last_name for all Active or Retread students and then LEFT JOIN the highest course_id, s_date, e_date, and int_date for the those students where the s_date is since the status_change_date if status is 'Retread'. Then LEFT JOIN the highest optional_courses_opcourse_id, s_date, and e_date from the students_have_optional_courses TABLE where the students_have_optional_courses.s_date is greater or equal to the students_have_courses.s_date and the students_have_optional_courses.e_date IS NULL
Here is what is being returned:
student_id first_name last_name courses_course_id s_date e_date int_date optional_courses_opcourse_id s_date_1 e_date_1
------------ ------------ ----------- ------------------- ---------- ---------- ------------ ------------------------------ ---------- ----------
1 John Doe 2 2012-01-05 NULL NULL 1 2012-01-06 NULL
2 Jane Doe NULL NULL NULL NULL NULL NULL NULL
Here is what I want being returned:
student_id first_name last_name courses_course_id s_date e_date int_date optional_courses_opcourse_id s_date_1 e_date_1
------------ ------------ ----------- ------------------- ---------- ---------- ------------ ------------------------------ ---------- ----------
1 John Doe 2 2012-01-05 NULL NULL 5 2012-01-07 NULL
2 Jane Doe NULL NULL NULL NULL NULL NULL NULL
Everything is working except one thing, I cannot seem to get the highest students_have_optional_courses.optional_courses_opcourse_id no matter how I form the query
Sorry, I just solved this myself after writing this all out I think it helped me think of the solution.
Here is the solution query:
SELECT
`students_and_courses`.student_id,
`students_and_courses`.first_name,
`students_and_courses`.last_name,
`students_and_courses`.courses_course_id,
`students_and_courses`.s_date,
`students_and_courses`.e_date,
`students_and_courses`.int_date,
`students_optional_courses`.optional_courses_opcourse_id,
`students_optional_courses`.s_date,
`students_optional_courses`.e_date
FROM (
SELECT
`c_s_a_s`.student_id,
`c_s_a_s`.first_name,
`c_s_a_s`.last_name,
`c_s_a_s`.courses_course_id,
`c_s_a_s`.s_date,
`c_s_a_s`.e_date,
`c_s_a_s`.int_date
FROM (
SELECT
`students`.student_id,
`students`.first_name,
`students`.last_name,
`students_have_courses`.courses_course_id,
`students_have_courses`.s_date,
`students_have_courses`.e_date,
`students_have_courses`.int_date
FROM
`students`
LEFT OUTER JOIN `students_have_courses`
ON (
`students_have_courses`.`students_student_id` = `students`.`student_id` AND ((
`students_have_courses`.`s_date` >= `students`.`status_change_date` AND
`students`.current_status = 'Retread' ) OR
`students`.current_status = 'Active')
)
WHERE
`students`.current_status = 'Active' OR
`students`.current_status = 'Retread'
) `c_s_a_s`
ORDER BY
`c_s_a_s`.`courses_course_id` DESC
) `students_and_courses`
LEFT OUTER JOIN (
SELECT
*
FROM
`students_have_optional_courses`
ORDER BY
`students_have_optional_courses`.optional_courses_opcourse_id DESC
) `students_optional_courses`
ON (
`students_optional_courses`.students_student_id = `students_and_courses`.student_id AND
`students_optional_courses`.s_date >= `students_and_courses`.s_date AND
`students_optional_courses`.e_date IS NULL
)
GROUP BY
`students_and_courses`.student_id;
© Stack Overflow or respective owner