【问题标题】:Left Join Not Joining with a Single Record左连接不与单个记录连接
【发布时间】:2016-04-22 05:49:27
【问题描述】:

我有以下疑问:

Insert into cet_database.dbo.termData
    (
        termID,
        studentID,
        course,
        [current],
        program,
        StbyCurrentClassID,
        class,
        classCode,
        cancelled
    )
    Select
        fm_stg.classByStudent_termData_assessmentData.termID,
        fm_stg.classByStudent_termData_assessmentData.studentID,
        fm_stg.classByStudent_termData_assessmentData.class_code,
        case when fm_stg.classByStudent_termData_assessmentData.[current] = 'Yes' then 1 else 0 end,
        fm_stg.classByStudent_termData_assessmentData.program,
        fm_stg.classByStudent_termData_assessmentData.classByStudentID,
        fm_stg.classByStudent_termData_assessmentData.class,
        fm_stg.classByStudent_termData_assessmentData.classID,
        case when fm_stg.classByStudent_termData_assessmentData.cancelled_flag = 1 then 1 else 0 end
From fm_stg.classByStudent_termData_assessmentData left outer join termData
    On fm_stg.classByStudent_termData_assessmentData.class_code = termData.course
    and fm_stg.classByStudent_termData_assessmentData.termID = termData.termID
    and fm_stg.classByStudent_termData_assessmentData.studentID = fm_stg.classByStudent_termData_assessmentData.studentID
Where termData.StbyCurrentClassID is null

在将数据导入我的数据库表之前,我使用该查询将数据从另一个数据库 (fm_stg.classByStudent_termData_assessmentData) 导入临时表。此特定查询是一个更大的存储过程的一部分,该存储过程将数据导入到与termData 相关的多个表中。

当我运行存储过程时,我将记录插入fm_stg.classByStudent_termData_assessmentData,但没有插入termData。遇到此问题时,我只插入一条记录,但它适用于我之前所做的 10,000 条记录。我使用左连接来确定数据库表中已经存在的内容和不存在的内容,然后从临时表中获取相关记录。但是,有了这个记录:

316a, 39520, DEC 10, Yes, DEC10, 105713, DEC 10 (18), 6078, NULL, 2

选择不返回任何内容 - 这是为什么呢?我的termData 表中肯定不存在该记录,并且记录从暂存表插入到我的所有其他表中。 sproc 运行事务中的所有插入操作,以避免出现这种情况,即在某些表中插入记录而不在其他表中插入记录,但它似乎不起作用。

【问题讨论】:

  • 嗯,没有得到记录的唯一原因应该是WHERE 子句。删除它并运行更改后的选择查询以查看您意外得到的结果。
  • 你能创建一个重现问题的 SQL Fiddle 吗?我认为查询没有任何问题。
  • @TabAlleman 我尝试在 SQL Fiddle 中创建它(我以前没有使用过),但我一生都无法让它做任何事情,例如创建一个表。编辑:它似乎在 Firefox 中不起作用......将创建一个演示。
  • @ThorstenKettner 如果我去掉 where 子句,我会得到 666 条相同的记录。
  • 好的,我确定您看到的记录有一个 termID 和 class_code 已经在表中,因此不会插入记录。

标签: sql sql-server database join


【解决方案1】:

您说查询适用于前 10,000 条记录,但不适用于当前记录。在您的查询中唯一看起来很奇怪的是ON 子句中的第三行,您可以在其中将字段(studentID)与其自身进行比较。

On fm_stg.classByStudent_termData_assessmentData.class_code = termData.course
and fm_stg.classByStudent_termData_assessmentData.termID = termData.termID
and fm_stg.classByStudent_termData_assessmentData.studentID = fm_stg.classByStudent_termData_assessmentData.studentID

我只是在这里猜测,但是由于ON 子句中的这一行,你也想比较学生证吗?因此,到目前为止,您可能很幸运查询有效,现在您偶然发现了学生证。我想ON 子句应该是这样的:

On fm_stg.classByStudent_termData_assessmentData.class_code = termData.course
and fm_stg.classByStudent_termData_assessmentData.termID = termData.termID
and fm_stg.classByStudent_termData_assessmentData.studentID = termData.studentID

顺便说一句,查询通过使用表别名变得更具可读性。在以下查询中,我使用ad 表示fm_stg.classByStudent_termData_assessmentDatatd 表示termData

Insert into cet_database.dbo.termData
(
  termID,
  studentID,
  course,
  [current],
  program,
  StbyCurrentClassID,
  class,
  classCode,
  cancelled
)
Select
  ad.termID,
  ad.studentID,
  ad.class_code,
  case when ad.[current] = 'Yes' then 1 else 0 end,
  ad.program,
  ad.classByStudentID,
  ad.class,
  ad.classID,
  case when ad.cancelled_flag = 1 then 1 else 0 end
From fm_stg.classByStudent_termData_assessmentData ad
Left Outer Join termData td On  ad.class_code = td.course
                            And ad.termID     = td.termID
                            And ad.studentID  = td.studentID
Where td.StbyCurrentClassID is null;

此外,在检查存在时,为什么要使用反连接技巧?您对直截了当的NOT EXISTS 有疑问吗?仅在真正需要时才使用技巧。查询更好读如下:

Insert into cet_database.dbo.termData
(
  termID,
  studentID,
  course,
  [current],
  program,
  StbyCurrentClassID,
  class,
  classCode,
  cancelled
)
  Select
    termID,
    studentID,
    class_code,
    case when [current] = 'Yes' then 1 else 0 end,
    program,
    classByStudentID,
    class,
    classID,
    case when cancelled_flag = 1 then 1 else 0 end
  From fm_stg.classByStudent_termData_assessmentData ad
  Where Not Exists
  (
     Select *
     From termData td 
     Where ad.class_code = td.course
       And ad.termID     = td.termID
       And ad.studentID  = td.studentID
);

使用另一个 DBMS,您甚至可以使用不相关的 NOT IN(即 Where (class_code, termId, studenId) Not In (Select ...)),因此甚至不会出现像您这样的错字,但 SQL Server 在 IN 子句中没有元组不幸的是。

【讨论】:

  • 我没有特别好的理由使用“反加入”技巧,除了熟悉 - 感谢您提出其他建议。我认为Not Exists 的性能更好?我认为我遇到的问题是记录插入到很多相关表中,但没有插入到termData 表中。我仍然不明白为什么这是来自我的存储过程,但是如果我删除相关表中的所有记录,它似乎可以工作。这首先是因为我的来源(不是我的链接服务器/数据库)的不良记录。感谢您的帮助。
猜你喜欢
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-28
  • 1970-01-01
  • 1970-01-01
  • 2014-06-22
  • 1970-01-01
相关资源
最近更新 更多