我的查询因不完整的where子句而丢失数据

时间:2010-11-23 22:07:40

标签: sql sql-server tsql stored-procedures

我知道问题出在我的WHERE子句中,但我没有一个很好的解决方案来纠正这个问题。

如果第2部分中的条目未标记为已删除且链接到标记为已删除的第3条条目,则我将完全丢失该条目。

任何帮助都将不胜感激。

p.s同样的事情也发生在3到4之间 不幸的是,在我的时间之前,桌面结构无法改变。

Table       FK         PK         bit
------------------------------------------
Section1 |  JobID   | Sect1ID | isDeleted
Section2 |  Sect1ID | Sect2ID | isDeleted
Section3 |  Sect2ID | Sect3ID | isDeleted
Section4 |  Sect3ID | Sect4ID | isDeleted

存储过程:

    @JobId int
    AS
SET NOCOUNT ON

SELECT J.Section1,
    J.Section2,
    J.Section3,
    J.Section4,
    S1.Id AS Section1Id,
    S1.[Order] + 1 AS S1Order,
    S1.Text AS S1Text,
    S2.Id AS Section2Id,
    S2.Text AS S2Text,
    S2.[Order] AS S2Order,
    S3.Id AS Section3Id,
    S3.Text AS S3Text,
    S3.[Order] + 1 AS S3Order,
    S4.Id AS Section4Id,
    S4.Text AS S4Text,
    S4.[Order] AS S4Order
       FROM JT_Jobs J 
       JOIN JT_Section1 S1 ON J.JobId = S1.JobId
  LEFT JOIN JT_Section2 S2 ON S1.Id = S2.Section1Id
  LEFT JOIN JT_Section3 S3 ON S2.Id = S3.Section2Id
  LEFT JOIN JT_Section4 S4 ON S3.Id = S4.Section3Id
      WHERE J.JobId = @JobId 
        AND S1.IsDeleted = 0
        AND (s2.IsDeleted is null or s2.IsDeleted = 0) 
        AND (s3.IsDeleted is null or s3.IsDeleted = 0) 
        AND (s4.IsDeleted is null or s4.IsDeleted = 0)
   ORDER BY S1.[Order], S2.[Order], S3.[Order], S4.[Order]

3 个答案:

答案 0 :(得分:3)

将连接条件放在join子句中而不是where子句

  From JT_Jobs J
     Join JT_Section1 S1 
         On S1.JobId = J.JobId
            And S1.IsDeleted = 0
     Left Join JT_Section2 S2
         On S2.Section1Id=S1.Id 
            And (s2.IsDeleted is null or s2.IsDeleted = 0)  
     Left Join JT_Section3 S3 
         On S3.Section2Id = S2.iD
            And (s3.IsDeleted is null or s3.IsDeleted = 0)  
     Left Join JT_Section4 S4
         ON S4.Section3Id = S3.Id
            And (s4.IsDeleted is null or s4.IsDeleted = 0)    
  Where J.JobId = @JobId  

....解释,where子句中的谓词(布尔条件)仅在处理完所有连接后才被评估。

通过检查连接的两边,在所有连接条件为真的结果集中添加记录,然后 然后 ,处理(逻辑)连接,如果它是外连接,从外侧添加回来的 的记录在另一侧有匹配的记录。因此,连接条件仅应用于内侧,而外侧的记录则应用于内侧的记录。

因此,在处理完所有连接之后,在where子句中放置一个条件会导致它应用于最后一个中间结果集。此时所有这些外部记录都已添加回来,并且对于影响外部联接外侧的条件,它将消除在外部联接的后半部分中重新添加的所有记录,从而有效地将其转换为回到内部联接。

答案 1 :(得分:0)

sN.IsDeleted = 0添加到LEFT JOIN子句中,而不是WHERE子句中。

答案 2 :(得分:0)

如果在左连接右侧的表中引用where子句中的字段(除非ID为null),则将其转换为内连接。您必须将这些条件放入连接条件中。