我有一个关于三元布尔逻辑的问题,它影响我们在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一样吗?
答案 0 :(得分:2)
创建计算列:
Location AS COALESCE(Country, State)
,将其编入索引并像往常一样进行比较:
SELECT *
FROM Region r1
JOIN Region r2
ON r2.Location = r1.Location
如果Location
和NULL
都是Country
,则 State
将为NULL
。
<强>更新强>
如果Country
和State
可以互相比较,请创建一个附加列,显示使用哪一个:
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
)