2016-07-15 36 views
1

我的INNER JOIN正在過濾掉太多,或者我看不出有什麼不同。我的INNER JOIN正在過濾掉太多

我想在同一臺服務器上合併來自2個不同數據庫的2個表。

我的第一步是要找到所有匹配的值:

SELECT intl.* 
FROM tblData intl 
INNER JOIN [db].dbo.tblData us 
ON  intl.DataID = us.DataID 
AND intl.AnotherID = us.AnotherID 
AND intl.DataValue = us.DataValue 
AND intl.TextValue = us.TextValue 
AND intl.DefaultValue = us.DefaultValue 
AND intl.RateValue = us.RateValue 
AND intl.YetAnotherID = us.YetAnotherID 

我已經檢查的所有列,它們是相同的類型和相同的VARCHAR值。所以這個查詢應該帶回所有的匹配值。

但是......情況並非如此。它只返回200+的記錄,在那裏,如果我運行此查詢後,我插入200+記錄到一個臨時表:

SELECT intl.DataID 
FROM tblData intl 
LEFT JOIN TempDataTable TDT 
ON  TDT.DataID = intl.DataID 
AND TDT.AnotherID = intl.AnotherID 
AND TDT.DataValue = intl.DataValue 
AND TDT.TextValue = intl.TextValue 
AND TDT.DefaultValue = intl.DefaultValue 
AND TDT.RateValue = intl.RateValue 
AND TDT.YetAnotherID = intl.YetAnotherID 
WHERE TDT.DataID IS NULL 

該查詢返回1500+行。

我已經運行了一個與美國數據類似的查詢,發現相同的差異(返回1500+行)。

我只看了一條記錄,看看是否可以識別出一些令人毛骨悚然的東西,並且我發現每張表(INTL和US)的記錄完全相同!

DataID: 1 
AnotherID: 1 
DataValue: NULL 
TextValue: NORMAL 
DefaultValue: 0 
RateValue: NULL 
YetAnotherID: 1 

我想象我的內連接的結構上找到2個表之間的差異,但我無法看到它。

任何想法會導致這種情況?

+4

可能是'NULL'值。 'NULL'不等於任何東西,甚至不是另一個'NULL'。因此,在比較「NULL」列時,它將無法通過相等性檢查,從而使您的'LEFT JOIN'數字膨脹。 – Siyual

+0

真的......我不知道。你有任何建議讓這個工作,或者我應該不匹配可能是NULL的列? – webdad3

+2

一個處理這種方式將這些空值實際值:'COALESCE(TDT.DataValue, '@#$%!')= COALESCE(TDT.DataValue, '@#$%!')' – shawnt00

回答

2

這可能是由你在表中沒有您LEFT JOIN的平等檢查有NULL值造成的。

NULL值不等於任何東西,甚至不是相同數據類型的另一個NULL

爲了解決這個問題,你可以在兩側除了添加一個檢查到ON子句NULL值現有JOIN條件:

SELECT intl.DataID 
FROM tblData intl 
LEFT JOIN TempDataTable TDT 
    ON (
      (TDT.DataID IS NULL AND intl.DataID IS NULL)    
      OR TDT.DataId = intl.DataId 
     ) 
    AND (
      (TDT.AnotherID IS NULL AND intl.AnotherID IS NULL)  
      OR TDT.AnotherId = intl.AnotherId 
     ) 
    AND (
      (TDT.DataValue IS NULL AND intl.DataValue IS NULL)  
      OR TDT.DataValue = intl.DataValue 
     ) 
    AND (
      (TDT.TextValue IS NULL AND intl.TextValue IS NULL)  
      OR TDT.TextValue = intl.TextValue 
     ) 
    AND (
      (TDT.DefaultValue IS NULL AND intl.DefaultValue IS NULL) 
      OR TDT.DefaultValue = intl.DefaultValue 
     ) 
    AND (
      (TDT.RateValue IS NULL AND intl.RateValue IS NULL) 
      OR TDT.RateValue = intl.RateValue 
     ) 
    AND (
      (TDT.YetAnotherID IS NULL AND intl.YetAnotherID IS NULL) 
      OR TDT.YetAnotherID = intl.YetAnotherID 
     ) 
WHERE TDT.DataID IS NULL 
1

INNER JOIN是做什麼它應該和正在恢復從tblData(美國)和tblData(國際)只有行,其中全部您的tdt = intl條件適用。如果它是一個NULL值,那麼coalesce()將是你想要使用的。試想一下:

select 1 where null = null 
select 2 where coalesce(null,2) = coalesce(null,2) 
1

EXISTS可以很好的爲這個查詢。

SELECT 
    intl.DataID 
FROM 
    tblData intl 
WHERE 
    NOT EXIST 
    (
     SELECT TOP 1 FROM TempDataTable TDT 
     WHERE 
      TDT.DataID = intl.DataID AND 
      TDT.AnotherID = intl.AnotherID AND 
      TDT.DataValue = intl.DataValue AND 
      TDT.TextValue = intl.TextValue AND 
      TDT.DefaultValue = intl.DefaultValue AND 
      TDT.RateValue = intl.RateValue AND 
      TDT.YetAnotherID = intl.YetAnotherID 
    ) 
2

我喜歡這種方法來處理NULL等式比較。

More details about it here

SELECT intl.* 
FROM tblData intl 
     INNER JOIN [db].dbo.tblData us 
     ON EXISTS (SELECT intl.DataID, 
          intl.AnotherID, 
          intl.DataValue, 
          intl.TextValue, 
          intl.DefaultValue, 
          intl.RateValue, 
          intl.YetAnotherID, 
        INTERSECT 
        SELECT us.DataID, 
          us.AnotherID, 
          us.DataValue, 
          us.TextValue, 
          us.DefaultValue, 
          us.RateValue, 
          us.YetAnotherID) 
2
Values null not take in your query. Use isnull(value, 0) for type value number and isnull(value, '') for type value chararctere 

    SELECT intl.DataID 
    FROM tblData intl 
    inner JOIN TempDataTable TDT 
    ON  isnull(TDT.DataID, 0) = isnull(intl.DataID, 0) 
    AND isnull(TDT.AnotherID, 0) = isnull(intl.AnotherID, 0) 
    AND isnull(TDT.DataValue, '') = isnull(intl.DataValue, '') 
    AND isnull(TDT.TextValue, '') = isnull(intl.TextValue, '') 
    AND isnull(TDT.DefaultValue, 0) = isnull(intl.DefaultValue, 0) 
    AND isnull(TDT.RateValue, '') = isnull(intl.RateValue, '') 
    AND isnull(TDT.YetAnotherID, 0) = isnull(intl.YetAnotherID, 0)