使用非Equi Join的有效用例是什么? >,> =,<,< =,<>

时间:2017-03-16 15:30:57

标签: sql performance tsql join

在FROM语句中使用运算符的目的是什么?互联网上提供的大多数示例都可以通过在WHERE语句中添加类似的标准来解决。

示例:

SELECT T1.OrderNum, T1.SpecialOfferAppliedDate AS SOAD, T1.SpecialOfferID, T2.StartDate, T2.EndDate
FROM OrderDetail AS T1 
   INNER JOIN SpecialOffer AS T2 
        ON T1.SpecialOfferID = T2.SpecialOfferID 
       AND T1.SOAD < T2.EndDate 
       AND T1.SOAD >= T2.StartDate

使用WHERE语句的示例:

SELECT T1.OrderNum, T1.SpecialOfferAppliedDate AS SOAD, T1.SpecialOfferID, T2.StartDate, T2.EndDate
FROM OrderDetail AS T1 
  INNER JOIN SpecialOffer AS T2 
          ON T1.SpecialOfferID = T2.SpecialOfferID 
WHERE T1.SOAD < T2.EndDate 
  AND T1.SOAD >= T2.StartDate
编辑:有人可以提供任何查询,我必须通过非Equi加入加入吗?在这一点上,它似乎只与以下内容相关:个人偏好或巨额表的性能提升

5 个答案:

答案 0 :(得分:1)

可以使用执行所有工作的WHERE语句重写所有连接。

SELECT table1.cols ..., table2.cols ... 
FROM table1 
JOIN table2 ON TRUE
WHERE table1.id = table2.id 

UNION SELECT cols, null ... -- for LEFT or FULL JOIN
FROM table1 WHERE id NOT IN (SELECT id FROM table2)

UNION SELECT null ..., cols -- for RIGHT or FULL JOIN
FROM table2 WHERE id NOT IN (SELECT id FROM table1)

注意使用LEFT | RIGHT | FULL JOIN

WHERE案例更加难以处理

我个人更喜欢在JOIN ... ON而不是WHERE条款中表达有问题的关系。在您的示例中,可以称为“适用于此订单的特殊优惠”,其中“适用于此订单”同时具有标识和时间组件。

答案 1 :(得分:1)

这完全取决于可读性和可懂度。

当您将两个表连接在一起时,将该连接的逻辑保持在一个位置是有意义的。在您的示例中,逻辑匹配记录依赖于外键关系(T1.SpecialOfferID = T2.SpecialOffID)以及购买和特价商品的日期。日期逻辑显示为连接的组成部分 - 您只想检索适合该日期范围的匹配项。

在“where”子句中,您可能还有其他限制,这些限制不会影响加入逻辑 - 订单的价值,特价商品的创建者,等等。

这通常是一个解释问题,哪个子句是连接的固有部分,它是对数据集的一种改进。实际上,这两种用法是等价的。

“非equi”部分 - 我相信 - 只与它定义连接的方式相关。在您的示例中,有一些逻辑表明“与ID匹配的记录也应该适合日期范围”,以使联接有效“。

在join语句中包含比较的用例是业务域仅在满足整个连接条件时才建议这些记录属于一起的位置。

在where子句中包含比较的用例是精炼所需结果的用例,但不定义业务域中哪些记录“属于一起”。

答案 2 :(得分:1)

我不能想到两个表格中任何与不平等关系自然相关的例子。考虑一下我可能会利用其使用能力的查询,仍然不难想象。假设我想按年龄对人进行排名。为简单起见,假设没有联系。

select p.name, count(*) as age_rank
from people p inner join people p2 on p2.birth_date <= p.birth_date
group by p.name

使用高级SQL功能(如分析函数)不再需要许多具有自联接功能的技巧。

您的问题似乎侧重于在fromwhere之间移动逻辑条件。一旦开始使用外连接,就不再具有自由,因为查询在语义上不再相同。

答案 3 :(得分:1)

当天早些时候,SQL 2005及更早版本过去依赖于SQL Server的维护方式,可能会声称它有时会稍快一些。我已经习惯了这样做,因为从逻辑上来说,我可以更快地限制范围并首先选择最大的表格并获得更大的收益。

EG:假设我有三个表A,B,C。并且A和B在Dt(日期)字段上有数百万行和一些索引。而另一张表只有几万行。我会做很多次这样的事情:

Select (columns)
From a
     inner join b on a.Id = b.FId
         and a.Id >= (somedate)
     inner join c on b.Id = c.FId

一般来说,我更有意义的是尽快限制范围,而就发动机来说,来自&#39;来自&#39;声明实际上是我在SQL Server引擎中首先从我所读过的内容中看到的。所以我真的采取了一套说数百万的所有潜力然后做一个where语句,只知道内连接总是说要求必须匹配返回和进一步限制范围。 &#39; Where&#39;子句确实做同样的事情,但是在&#39; From&#39;之后进行评估。声明因此可以合理地得出结论会更慢。

然而,在开发圈中,性能与可读性之间存在着持续的争论。所以,如果我有类似的东西:

Select (columns)
From a
     inner join b on a.Id = b.FId
         and a.Id >= (somedate)
         and a.ocol = (criteria)
     left outer join c on b.Id = c.FId
where c.ocol = (criteria)

有人可以告诉我:&#34;嘿,你只是从那里获得了0.00001的提升,那么把它全部放在Where子句中怎么样?&#34;它有时是性能与可读性的平衡行为。如果事情非常滞后,虽然我可以理所当然地说某种方式可能会更好。但总的来说,我读到大约在2012年,或者可能是2008 R2,或者说微软重新设计引擎,它可以更高效地编译它,实际上它不再真正节省时间。如果你愿意,你可以自己测试一下:

在SQL Management Studio上运行:

SET STATISTICS TIME ON;

你会看到这样的事情:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 2 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 2 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 8 ms.

在“消息”选项卡上。你当然也可以做更重的“客户统计”。从视图面板中选项卡,查看更多详细信息。可以说这只是许多人使用的一种语法技巧,可以更有效地利用引擎执行来更快地限制范围。然而,重新加工可能不会让它变得更好。我仍然使用它,虽然我自己编码,你习惯了事情:)

答案 4 :(得分:0)

INNER JOIN是您应该使用的ANSI语法。如果可以的话,避免添加到WHERE是最好的。

另外, 它通常被认为更具可读性,尤其是当您加入大量表格时,可以在需要时使用OUTER JOIN轻松替换。

在表现方面,他们没有差异。