MySQL LEFT OUTER JOIN 虚拟表

标签 mysql left-join

我正在处理一个非常复杂的查询,让我尝试向您解释一下。这是我的 MySQL 数据库中的表:

学生表

--- `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 表

--- `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 表

--- `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

这是我到目前为止的查询

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;

我想要返回的是所有活跃或重读学生的学生 ID、名字和姓氏,然后 LEFT JOIN 那些学生的最高 course_id、s_date、e_date 和 int_date,其中 s_date 自 status_change_date 如果状态是“翻新”。然后从 Students_have_Optional_courses 表中 LEFT JOIN 最高的Optional_courses_opcourse_id、s_date 和 e_date,其中 Students_have_Optional_courses.s_date 大于或等于 Students_have_courses.s_date 并且 Students_have_Optional_courses.e_date 为 NULL

这是返回的内容:

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

这是我想要返回的内容:

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

除了一件事之外,一切正常,无论我如何形成查询,我似乎都无法获得最高的 Students_have_Optional_courses.Optional_courses_opcourse_id

抱歉,我在写完这些内容后自己解决了这个问题,我认为这帮助我想到了解决方案。

这是解决方案查询:

    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;

最佳答案

这是我自己调试时发现的答案:

    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;

我需要在 LEFT JOINING 之前选择并订购 Students_have_Optional_courses 表。我希望这可以帮助任何其他人寻找这样的答案。

关于MySQL LEFT OUTER JOIN 虚拟表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13364913/

相关文章:

python - 我无法将 MySQLdb 导入我的 Python 程序

sql - 带有一些空值逻辑的 PostgreSQL 内连接和外连接

mysql - 查询 : Count how many times a parameter in one table does not exist in another

php - 从 4 个表中检索数据

mysql - SQLSTATE[HY000] : General error: 1366 Incorrect integer value:

mysql - 简单的服务器处理路由并给出错误nodejs mysql

mysql - 执行mysql查询时出现重复列名错误?

php - 比较两列之间的日期时 LEFT JOIN 不起作用

r - 如何 left_join() 两个数据集但只从其中一个数据集中选择特定列?

MySql group by with where 条件不起作用