SQL Server JOIN缺少NULL值

时间:2013-01-16 19:15:57

标签: sql sql-server

假设我有以下两个表:

      Table1:                                Table2:
Col1:      Col2:     Col3:             Col1:       Col2:       Col4:
a          b         c                 a           b           d
e          <null>    f                 e           <null>      g
h          i         j                 h           i           k
l          <null>    m                 l           <null>      n
o          <null>    p                 o           <null>      q

现在,我想在Col1Col2上加入这些表,并将整个集合恢复为:

     Result:
Col1:      Col2:     Col3:     Col4:
a          b         c         d
e          <null>    f         g
h          i         j         k
l          <null>    m         n
o          <null>    p         q

所以,我尝试了一个SQL:

SELECT Table1.Col1, Table1.Col2, Table1.Col3, Table2.Col4
FROM Table1 INNER JOIN Table2
ON Table1.Col1 = Table2.Col1 
AND Table1.Col2 = Table2.Col2

但它与NULL中的Col2值不匹配,所以我最终得到:

     Result:
Col1:      Col2:     Col3:     Col4:
a          b         c         d
h          i         j         k

我怎样才能得到我想要的结果?

谢谢!

9 个答案:

答案 0 :(得分:73)

您可以明确指出联接:

SELECT Table1.Col1, Table1.Col2, Table1.Col3, Table2.Col4
FROM Table1 INNER JOIN
     Table2
      ON (Table1.Col1 = Table2.Col1 or Table1.Col1 is NULL and Table2.Col1 is NULL) AND
         (Table1.Col2 = Table2.Col2 or Table1.Col2 is NULL and Table2.Col2 is NULL)

在实践中,我更有可能在连接条件中使用coalesce()

SELECT Table1.Col1, Table1.Col2, Table1.Col3, Table2.Col4
FROM Table1 INNER JOIN
     Table2
     ON (coalesce(Table1.Col1, '') = coalesce(Table2.Col1, '')) AND
        (coalesce(Table1.Col2, '') = coalesce(Table2.Col2, ''))

其中''不是任何一个表中的值。

请注意。在大多数数据库中,使用任何这些结构都会阻止使用索引。

答案 1 :(得分:26)

使用Left Outer Join而不是Inner Join来包含具有NULLS的行。

SELECT Table1.Col1, Table1.Col2, Table1.Col3, Table2.Col4
FROM Table1 LEFT OUTER JOIN 
    Table2 ON Table1.Col1 = Table2.Col1 
    AND Table1.Col2 = Table2.Col2

有关详细信息,请参阅此处:http://technet.microsoft.com/en-us/library/ms190409(v=sql.105).aspx

答案 2 :(得分:15)

尝试使用ISNULL功能:

SELECT Table1.Col1, Table1.Col2, Table1.Col3, Table2.Col4
FROM Table1 
INNER JOIN Table2
   ON Table1.Col1 = Table2.Col1 
   AND ISNULL(Table1.Col2, 'ZZZZ') = ISNULL(Table2.Col2,'ZZZZ')

'ZZZZ'在表中永远不会有任意值。

答案 3 :(得分:8)

肮脏而快速的黑客攻击:

SELECT Table1.Col1, Table1.Col2, Table1.Col3, Table2.Col4
FROM Table1 INNER JOIN Table2 ON Table1.Col1 = Table2.Col1
 AND ((Table1.Col2 = Table2.Col2) OR (Table1.Col2 IS NULL AND Table2.Col2 IS NULL))

答案 4 :(得分:1)

你可以像那样映射

select * from tableA a
join tableB b on isnull(a.colID,'') = isnull(b.colId,'')

答案 5 :(得分:0)

由于某种原因,我无法使其与外部联接一起使用。

所以我用过:

SELECT * from t1 where not Id in (SELECT DISTINCT t2.id from t2)

答案 6 :(得分:0)

唯一正确的答案是不连接具有空值的列。这会很快导致不良行为。

例如notull(b.colId,''):如果您的数据中有空字符串怎么办?联接可能重复行,我猜在这种情况下不希望这样做。

答案 7 :(得分:0)

declare @Table1 as Table(Col1 varchar(1),Col2 varchar(1), Col3 varchar(1))
declare @Table2 as Table(Col1 varchar(1),Col2 varchar(1), Col4 varchar(1))
insert into @Table1
values('a',          'b',     'c'),
('e',          null,    'f'), 
('h',          'i'  ,   'j'), 
('l',          null  ,  'm'), 
('o',          null  ,  'p') 
insert into @Table2
values('a',          'b',     'd'),
('e',          null,    'g'), 
('h',          'i'  ,   'k'), 
('l',          null  ,  'n'), 
('o',          null  ,  'q') 


select * from @Table1 tbl1
join @Table2 tbl2
on tbl1.Col1 =tbl2.Col1
and isnull(tbl1.Col2,0) =isnull(tbl2.Col2,0)

输出:

 Col1   Col2    Col3    Col1    Col2    Col4
 a      b       c       a       b       d
 e      NULL    f       e       NULL    g
 h      i       j       h       i       k
 l      NULL    m       l       NULL    n
 o      NULL    p       o       NULL    q

答案 8 :(得分:-1)

尝试在连接中使用其他条件:

SELECT Table1.Col1, Table1.Col2, Table1.Col3, Table2.Col4
FROM Table1 
INNER JOIN Table2
ON (Table1.Col1 = Table2.Col1 
    OR (Table1.Col1 IS NULL AND Table2.Col1 IS NULL)
   )