连接中“和”和“where”之间的区别

时间:2010-04-01 08:52:56

标签: sql join

之间的区别是什么
SELECT DISTINCT field1 
  FROM table1 cd  
  JOIN table2 
    ON     cd.Company = table2.Name 
       and table2.Id IN (2728) 

SELECT DISTINCT field1 
  FROM table1 cd  
  JOIN table2 
    ON cd.Company = table2.Name 
 where table2.Id IN (2728) 

都返回相同的结果并且两者都具有相同的解释输出

5 个答案:

答案 0 :(得分:29)

首先存在语义差异。如果有连接,则表示两个表之间的关系由该条件定义。因此,在您的第一个示例中,您表示这些表与cd.Company = table2.Name AND table2.Id IN (2728)相关联。当您使用WHERE子句时,您说该关系由cd.Company = table2.Name定义,并且您只希望条件table2.Id IN (2728)适用的行。尽管这些答案给出了相同的答案,但对于阅读代码的程序员来说,这意味着完全不同的事情。

在这种情况下,WHERE子句几乎可以肯定你的意思所以你应该使用它。

其次,在使用LEFT JOIN而不是INNER JOIN的情况下,结果实际上存在差异。如果将第二个条件作为连接的一部分包含在内,则在条件失败时仍将获得结果行 - 您将从左表中获取值,并为右表获取空值。如果将条件包含在WHERE子句中并且该条件失败,则根本不会获取该行。

这是一个证明这一点的例子。

查询1(WHERE):

SELECT DISTINCT field1
  FROM table1 cd
  LEFT JOIN table2
    ON cd.Company = table2.Name
 WHERE table2.Id IN (2728);

结果:

field1
200

查询2(AND):

SELECT DISTINCT field1
  FROM table1 cd
  LEFT JOIN table2
    ON cd.Company = table2.Name
   AND table2.Id IN (2728);

结果:

field1
100
200

使用的测试数据:

CREATE TABLE table1 (Company NVARCHAR(100) NOT NULL, Field1 INT NOT NULL);
INSERT INTO table1 (Company, Field1) VALUES
('FooSoft', 100),
('BarSoft', 200);

CREATE TABLE table2 (Id INT NOT NULL, Name NVARCHAR(100) NOT NULL);
INSERT INTO table2 (Id, Name) VALUES
(2727, 'FooSoft'),
(2728, 'BarSoft');

答案 1 :(得分:6)

SQL来自relational algebra

查看差异的一种方法是JOIN是对集合的操作,可以在结果中生成比原始表中更多的记录或更少的记录。另一方面,WHERE将始终限制结果的数量。

本文的其余部分是额外的解释。


有关联接类型的概述,请再次参阅article

当我说where条件总是会限制结果时,你必须考虑到当我们讨论两个(或更多)表上的查询时,你必须以某种方式配对来自这些表的记录,即使没有JOIN关键字。

所以在SQL中,如果表只是用逗号分隔,那么实际上你正在使用一个CROSS JOIN(笛卡尔积),它返回一个表中每一行的每一行。

由于这是两个表中行的最大组合数,因此交叉连接表上任何WHERE的结果都可以表示为JOIN操作。

但是,当你引入LEFT,RIGHT和FULL OUTER连接时,这个最大值有例外。

LEFT JOIN会将给定条件左表中的记录与右表中的记录连接起来,但是如果连接条件,则查看右表中任何记录的左表中的行不满足LEFT JOIN仍然会从左表返回一个记录,而在右表中的列中,它将返回NULL(RIGHT JOIN的工作方式类似,但是从另一侧起,FULL OUTER同时起作用)。

由于默认的交叉连接不返回那些记录,你不能用WHERE条件表达这些连接标准,并且你被迫使用JOIN语法(oracle是一个例外,带有SQL标准的扩展和to =运算符,但是其他供应商也没有接受这个标准。)

此外,连接通常但并不总是与现有的参照完整性一致,并建议实体之间的关系,但我不会给予那么多的重视,因为where条件可以做同样的事情(除了前面提到的情况)和对于一个好的RDBMS,在指定标准的地方不会产生任何影响。

答案 2 :(得分:3)

  • 联接用于反映实体关系
  • where子句过滤掉结果。

因此,join子句是“静态的”(除非实体关系发生变化),而where子句是特定于用例的。

答案 3 :(得分:1)

没有区别。 “ON”就像是“WHERE”的同义词,所以第二种类型的读取就像:

JOIN table2 WHERE cd.Company = table2.Name AND table2.Id IN (2728)

答案 4 :(得分:0)

当查询优化引擎将其分解为相关的查询运算符时,没有区别。