NULL を比較すると UNKNOWN が返る

NULL を比較すると UNKNOWN になります。
NULL 比較検索条件
NULL 値

create table [test] ( 
  id int identity(1, 1) primary key, 
  name1 char(5), 
  name2 char(5) 
)
go
insert into [test] ([name1], [name2]) 
values 
( 'AAAAA', 'AAAAA' ), 
( 'AAAAA', 'BBBBB' ), 
( 'AAAAA', null ), 
( null, 'AAAAA' ), 
( null, null )
go

なデータがあって、[name1] と [name2] が異なるデータを取りたい時に、下のようなクエリを書いたとします。

select [id] from [test] where 
  [name1] <> [name2] 

Java .NET だと、これで取れるでしょうが、SQL ではダメです。
id 3, 4 のデータが取れません。[name1] <> [name2] null は is null や is not null でないと比較出来ません。
もちろん次のクエリでもダメです。

select [id] from [test] where 
  not ([name1] = [name2]) 

null が混じった "=" や "<>" は UNKNOWN になり、not UNKNOWN は UNKNOWN になるので、これまた行が返ってきません。
うっかり、null = 〜 が false になると勘違いしていると、ハマるかもしれませんね。*1


正しくは、こんなクエリ

select [id] from [test] where 
  [name1] <> [name2] 
  or ([name1] is null and [name2] is not null) 
  or ([name1] is not null and [name2] is null)


以下、サンプルクエリ

create table [test] ( 
  id int identity(1, 1) primary key, 
  name1 char(5), 
  name2 char(5) 
)
go
insert into [test] ([name1], [name2]) 
values 
( 'AAAAA', 'AAAAA' ), 
( 'AAAAA', 'BBBBB' ), 
( 'AAAAA', null ), 
( null, 'AAAAA' ), 
( null, null )
go
select [id] from [test] where 
  [name1] <> [name2] 
go
select [id] from [test] where 
  not ([name1] = [name2]) 
go
select [id] from [test] where 
  [name1] <> [name2] 
  or ([name1] is null and [name2] is not null) 
  or ([name1] is not null and [name2] is null)
go
drop table [test]

.NET や Java(Groovy) の場合

.NET

var list = new List<dynamic>() {
  new { Id = 1, Name1 = "AAAAA", Name2 = "AAAAA" }, 
  new { Id = 2, Name1 = "AAAAA", Name2 = "BBBBB" }, 
  new { Id = 3, Name1 = "AAAAA", Name2 = (String)null }, 
  new { Id = 4, Name1 = (String)null, Name2 = "AAAAA" }, 
  new { Id = 5, Name1 = (String)null, Name2 = (String)null }, 
};
list.Where(m => m.Name1 != m.Name2)
  .ToList().ForEach(m => Console.WriteLine((int)m.Id));

Groovy

def list = [
  [id:1, name1:"AAAAA", name2:"AAAAA"], 
  [id:2, name1:"AAAAA", name2:"BBBBB"], 
  [id:3, name1:"AAAAA", name2:null], 
  [id:4, name1:null, name2:"AAAAA"], 
  [id:5, name1:null, name2:null], 
]
list.each { 
  if (it.name1 != it.name2) {
    println it.id
  }
}

*1:一瞬悩んだ…