带有可选NULL值的SQL Server JOIN

时间:2010-04-29 19:39:42

标签: sql sql-server-2008

想象一下,我们有两个表如下:

Trades
(
  TradeRef INT NOT NULL, 
  TradeStatus INT NOT NULL,
  Broker INT NOT NULL,
  Country VARCHAR(3) NOT NULL
)

CTMBroker
(
  Broker INT NOT NULL,
  Country VARCHAR(3) NULL
)

(为了本例的目的,这些已被简化)。现在,如果我们希望在Broker列上加入这两个表,并且如果国家/地区存在CTMBroker表中的,我们有以下两种选择:

SELECT T.TradeRef,T.TradeStatus
FROM Trades AS T
JOIN CTMBroker AS B ON B.Broker=T.Broker AND ISNULL(B.Country, T.Country) = T.Country

SELECT T.TradeRef,T.TradeStatus
FROM Trades AS T
JOIN CTMBroker AS B ON B.Broker=T.Broker AND (B.COUNTRY=T.Country OR B.Country IS NULL)

这些在逻辑上是等价的,但是在我们的数据库(SQL Server 2008,SP1)的这种特定情况下,为这两个查询生成了两个不同的执行计划,第二个版本在时间和逻辑上明显优于第一个版本读取。

我的问题确实如下:作为一般规则,(2)优先选择(1),或者这恰好恰好利用了2008 SP1中优化器的某些特定特性(因此可能会因未来版本而改变) SQL Server)。

2 个答案:

答案 0 :(得分:2)

我认为部分原因是ISNULL是一个函数,因此SQL不能使用表上的任何索引,而是必须扫描评估每一行的表。因此,我试图避免连接条件中的函数。

答案 1 :(得分:1)

你也可以尝试这个吗?

SELECT T.TradeRef,T.TradeStatus
FROM Trades AS T
JOIN CTMBroker AS B ON B.Broker=T.Broker AND B.COUNTRY=T.Country
UNION ALL
SELECT T.TradeRef,T.TradeStatus
FROM Trades AS T
JOIN CTMBroker AS B ON B.Broker=T.Broker AND B.Country IS NULL

UNION ALL通常优于OR,具体取决于优化器优化OR的能力。如果这与第二个查询的速度相同,则说明原因如此之快:优化程序能够看到有两个独立的条件并适当地使用索引。

在第一种情况下,因为您使用的是非sargable函数(ISNULL),所以无法使用索引。