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

发布于 2024-11-03 00:11:29 字数 1533 浏览 4 评论 0原文

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

在 SQL 中,如果您使用 Country 的外键连接 Region 表:(

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

注意:无论您使用 JOIN 还是 WHERE 合成,结果都是相同的)

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

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,反之亦然。

我们如何连接 [Country,State] 对,使其具有与以前相同的属性?:

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 相等一样运行?

  • 匹配时为 True
  • 不匹配时为 False
  • 某些操作数为空时为未知。

I've a question regarding ternary boolean logic that affects how to implement comparison between polymorphic entities in our LINQ provider.

In SQL, if you join the Region table using a foreign key to Country :

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

(note: the results are identical whether you use JOIN or WHERE synthax)

It will return the values where the condition is true, and not then the condition is false, or unknown (because some of the keys are null). So if we negate the condition:

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

We get the values where the condition is true (now different keys) and we will skip the ones that have same keys, or the ones that have some null value because the condition return unknown again. Even if we write it like this:

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

The unknown will be propagated so the nulls never appear for this simple condition. So far so good.

Now let's imagine that a Region can have a Country (for small European countries) or a State (for US, Russia, China...). If the region has a State it will have Country null and the other way around.

How could we join the pair [Country,State] so it have the same properties than before?:

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

This expression will return true if it joins, unknown otherwise. We would like that it returns unknown only in the case that all the fields are null, otherwise if we negate:

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

It returns no rows!. If we try a more convoluted expression:

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) 

Then it will return true when the pair matches, false otherwise, and never nothing. Then if we negate, it will return the values where all the rows are null, behaving differently than in the firs example.

So wich expression for comparing this pair will behave like an SQL equality?

  • True when matches
  • False when doesn't match
  • Unknown when some operand is null.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

-残月青衣踏尘吟 2024-11-10 00:11:29

创建一个计算列:

Location AS COALESCE(Country, State)

,为其建立索引并照常进行比较:

SELECT  *
FROM    Region r1
JOIN    Region r2
ON      r2.Location = r1.Location

如果 CountryState 都为 Location,则 Location 将为 NULLNULL

更新:

如果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

Create a computed column:

Location AS COALESCE(Country, State)

, index it and compare as usual:

SELECT  *
FROM    Region r1
JOIN    Region r2
ON      r2.Location = r1.Location

Location will be NULL if both Country and State are NULL.

Update:

If Country and State can be inter-comparable, create an additional column showing which one is used:

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

, index the two and use them in comparison:

SELECT  *
FROM    Region r1
JOIN    Region r2
ON      r2.LocationType = r1.LocationType
        AND r2.LocationID = r1.LocationID
无人问我粥可暖 2024-11-10 00:11:29

你能试试这个吗:

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
       )

Can you try this:

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
       )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文