在 MYSQL 中加入多个 table 时,一个 table 的数据丢失

Data from one table is missing while joining multiple tables in MYSQL

我有 3 个 table 叫 gps_stdnt_subj_xref a,gps_st_mark_fa1_fa3 b,gps_st_sa_mark_master c。第一个 table 包含科目列表,另外两个包含科目、学生及其分数。在第 3 个 table 中,我比第 2 个 table 有一些额外的主题(许多其他公共字段在第 2 个和第 3 个 table 中可用)。当我执行以下查询时,在输出中我只获得了常见主题的详细信息(主题在第二和第三 table 中可用)。我对 MYSQL 不是很熟悉(在 oracle 中,通常我们在附加值可用的字段末尾给出 (+),然后它将获取所有数据)。我尝试使用 LEFT Join 来获得预期的输出。但它只给出普通主题的输出。分享查询,请指导。

SELECT a.gps_subject,
       b.gps_st_mrk_gtot,
       b.gps_st_mrk_grade,
       b.gps_st_uid,
       b.gps_st_name,
       c.gps_st_sa_mark
  FROM gps_stdnt_subj_xref a
       LEFT JOIN (gps_st_mark_fa1_fa3 b, gps_st_sa_mark_master c)
          ON (    a.gps_subject = b.gps_st_mrk_subj
              AND b.gps_st_class = a.gps_class
              AND a.gps_subject = c.gps_st_sa_subject
              AND b.gps_st_uid = c.gps_st_sa_id
              AND c.gps_st_sa_class = b.gps_st_class
              AND b.gps_st_dvn = c.gps_st_sa_dvn
              AND a.gps_class = c.gps_st_sa_class)
 WHERE     a.gps_subject_status = 'Y'
       AND b.gps_st_mrk_stat = 'Y'
       AND b.gps_st_class = 'Class_07'
       AND b.gps_st_dvn = '07-C'

好了,都说完了:

  1. 你应该对两个 tables 使用一致的 LEFT JOIN
  2. 不要在 where 条件中对 LEFT JOINED table 应用 WHERE 条件:您将过滤结果行并仅获取具有匹配行的行

这是我对结果查询的外观的建议:

SELECT a.gps_subject,
       b.gps_st_mrk_gtot,
       b.gps_st_mrk_grade,
       b.gps_st_uid,
       b.gps_st_name,
       c.gps_st_sa_mark
  FROM gps_stdnt_subj_xref a
       LEFT JOIN ( select * from gps_st_mark_fa1_fa3
   Where gps_st_mrk_stat = 'Y'
       AND gps_st_class = 'Class_07'
       AND gps_st_dvn = '07-C'
) b
On a.gps_subject = b.gps_st_mrk_subj
              AND b.gps_st_class = a.gps_class

        LEFT JOIN gps_st_sa_mark_master c
          ON a.gps_subject = c.gps_st_sa_subject
              AND b.gps_st_uid = c.gps_st_sa_id
              AND c.gps_st_sa_class =b.gps_st_class
              AND b.gps_st_dvn = c.gps_st_sa_dvn
              AND a.gps_class = c.gps_st_sa_class
 WHERE     a.gps_subject_status = 'Y'

我已经在子查询中推送了 where 条件并使用了两次 LEFT JOIN。

============================================= ==============

EDITED:好的,OP 已经用重复的 "gps_subject" 和所有其他字段表示了很多行为空。这些应该是主题 table 在其他 table 上找不到匹配项的行。但是为什么会重复呢?再次查看查询后,"subject" table 似乎还包含一个 "class" (gps_class) 属性,因此在各种 [=54] 中重复相同的主题=]es.

原始查询在与 "class" 字段匹配的字段上对 "left joined" table(将其转回标准内部联接)进行了筛选(gpt_st_class).

假设 OP 需要限制 'Class_07' class 上的结果,我将此过滤器移至主题 table 并创建了结果 table。

SELECT a.gps_subject,
       b.gps_st_mrk_gtot,
       b.gps_st_mrk_grade,
       b.gps_st_uid,
       b.gps_st_name,
       c.gps_st_sa_mark
  FROM gps_stdnt_subj_xref a
       LEFT JOIN ( select * from gps_st_mark_fa1_fa3
                    Where gps_st_mrk_stat = 'Y'
                      AND gps_st_dvn = '07-C'
                 ) b
              On a.gps_subject = b.gps_st_mrk_subj
             AND b.gps_st_class = a.gps_class

       LEFT JOIN (select * from gps_st_sa_mark_master 
                   Where gps_st_sa_dvn = '07-C'     
                 ) c
              ON a.gps_subject = c.gps_st_sa_subject
             AND b.gps_st_uid = c.gps_st_sa_id
             AND a.gps_class = c.gps_st_sa_class
 WHERE a.gps_subject_status = 'Y'
   and a.gps_class='Class_07';

但是有一点我不清楚:两个 "mark" table 是为了 "student_id" 加入的。基本上这意味着,如果我们再次有一些 link,那么如果不匹配另一个 table 的数据,就不可能 return 数据。

除非我们有一个学生 table,或者关于这两个标记 table 之一的一些信息是 "complete"(这样它就可以与主题 table) 我能想到的最好的是:

SELECT a.gps_subject,
       b.gps_st_mrk_gtot,
       b.gps_st_mrk_grade,
       subj_class_stud.gps_st_uid,
       b.gps_st_name,
       c.gps_st_sa_mark
  FROM gps_stdnt_subj_xref a

       INNER JOIN (
         select gps_st_mrk_subj as subj, gps_st_uid as st_uid, gps_st_class st_class
           from gps_st_mark_fa1_fa3
          where gps_st_mrk_stat = 'Y'
            AND gps_st_dvn = '07-C'
          union all 
         select gps_st_sa_subject as subj, gps_st_sa_id as st_uid, gps_st_sa_class as st_class
           from gps_st_sa_mark_master 
          Where gps_st_sa_dvn = '07-C'  
       ) subj_class_stud
              on subj_class_stud.subj=a.gps_subject
             and subj_class_stud.st_class= a.gps_class

       LEFT JOIN ( select * from gps_st_mark_fa1_fa3
                    Where gps_st_mrk_stat = 'Y'
                      AND gps_st_dvn = '07-C'
                 ) b
              On subj_class_stud.subj = b.gps_st_mrk_subj
             AND b.gps_st_class = subj_class_stud.st_class
             and b.gps_st_uid = subj_class_stud.st_uid

       LEFT JOIN (select * from gps_st_sa_mark_master 
                   Where gps_st_sa_dvn = '07-C'     
                 ) c
              ON subj_class_stud.subj = c.gps_st_sa_subject
             AND subj_class_stud.st_uid = c.gps_st_sa_id
             AND subj_class_stud.st_class = c.gps_st_sa_class

 WHERE a.gps_subject_status = 'Y'
   and a.gps_class='Class_07';

最后一点是,当 "b" table 不匹配(例如,没有主题)时,OP 在结果集中会有一些空字段。 "c" table 上可能有相同的字段,但我们没有此信息。