将SQL Server中的元组与三元布尔逻辑进行比较

时间:2011-04-22 09:18:54

标签: sql-server linq null tuples boolean-logic

我有一个关于三元布尔逻辑的问题,它影响我们在LINQ提供程序中如何实现多态实体之间的比较。

在SQL中,如果使用国家/地区的外键加入Region表:

SELECT * From Region r1, Region r2
WHERE r1.Country == r2.Country 

(注意:无论使用JOIN还是WHERE synthax,结果都是相同的)

它将返回条件为true的值,而不是条件为false或未知(因为某些键为null)。所以如果我们否定这个条件:

SELECT * From Region r1, Region r2
WHERE r1.Country != r2.Country 

我们得到条件为真的值(现在是不同的键),我们将跳过具有相同键的值,或者具有一些空值的值,因为条件再次返回未知。即使我们这样写:

SELECT * From Region r1, Region r2
WHERE not(r1.Country == r2.Country) 

将传播未知,因此对于这种简单条件,空值永远不会出现。到现在为止还挺好。

现在让我们想象一个地区可以拥有一个国家(适用于欧洲小国家)或一个国家(适用于美国,俄罗斯,中国......)。如果该区域有一个State,它将具有Country null,反之亦然。

我们如何加入对[国家,州],以便它具有与以前相同的属性?:

SELECT * From Region r1, Region r2
WHERE r1.Country == r2.Country OR r1.State == r2.State

如果它加入,该表达式将返回true,否则将未知。我们希望它只在所有字段为空的情况下返回未知,否则如果我们否定:

SELECT * From Region r1, Region r2
WHERE not(r1.Country == r2.Country OR r1.State == r2.State)

它不返回任何行!如果我们尝试更复杂的表达:

SELECT * From Region r1, Region r2
WHERE (r1.Country == r2.Country AND r1.Country IS NOT NULL AND r2.Country IS NOT NULL)  
   OR (r1.State   == r2.State   AND r1.State   IS NOT NULL AND r2.State   IS NOT NULL) 

然后当对匹配时它将返回true,否则返回false,并且从不返回任何内容。然后,如果我们否定,它将返回所有行为空的值,其行为与第一个示例中的行为不同。

那么用于比较这一对的表达式将表现得像SQL一样吗?

  • 匹配时为真
  • 当不匹配时为假
  • 某些操作数为null时未知。

2 个答案:

答案 0 :(得分:2)

创建计算列:

Location AS COALESCE(Country, State)

,将其编入索引并像往常一样进行比较:

SELECT  *
FROM    Region r1
JOIN    Region r2
ON      r2.Location = r1.Location
如果LocationNULL都是Country,则

State将为NULL

<强>更新

如果CountryState可以互相比较,请创建一个附加列,显示使用哪一个:

LocationType AS CASE WHEN Country IS NOT NULL THEN 1 WHEN State IS NOT NULL THEN 2 END,
LocationId AS COALESCE(Country, State)

,索引两者并在比较中使用它们:

SELECT  *
FROM    Region r1
JOIN    Region r2
ON      r2.LocationType = r1.LocationType
        AND r2.LocationID = r1.LocationID

答案 1 :(得分:1)

你可以试试这个:

SELECT *
FROM Region r1
  JOIN Region r2
    ON ( r1.Country = r2.Country 
         AND r1.State IS NULL 
         AND r2.State IS NULL
       )
    OR ( r1.State = r2.State 
         AND r1.Country IS NULL 
         AND r2.Country IS NULL
       )