我的INNER JOIN过滤掉了太多

时间:2016-07-15 18:31:00

标签: sql sql-server

我的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多行)。

我看了1条记录只是为了看看我能辨别出什么东西,我发现每张桌子(INTL和US)的记录完全相同!

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

我想我的内部联接在结构上找到了两个表之间的差异,但我看不到它。

关于导致这种情况的任何想法?

5 个答案:

答案 0 :(得分:2)

这可能是由于您在LEFT JOIN的等式检查失败后表中的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}}值:

{{1}}

答案 1 :(得分: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 :(得分: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)

答案 3 :(得分:1)

INNER JOIN正在做它应该做的事情,那就是从tblData(us)和tblData(国际)返回行,其中你的tdt 全部 =国际条约适用。如果它是NULL值,则coalesce()将是您要使用的值。考虑一下:

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

答案 4 :(得分: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
     )