连接中"和"和"where"之间的区别

Mid*_*hat 16 sql join

什么区别

SELECT DISTINCT field1 
  FROM table1 cd  
  JOIN table2 
    ON     cd.Company = table2.Name 
       and table2.Id IN (2728) 
Run Code Online (Sandbox Code Playgroud)

SELECT DISTINCT field1 
  FROM table1 cd  
  JOIN table2 
    ON cd.Company = table2.Name 
 where table2.Id IN (2728) 
Run Code Online (Sandbox Code Playgroud)

两者都返回相同的结果,两者都有相同的解释输出

Mar*_*ers 30

首先是语义上的差异.如果有连接,则表示两个表之间的关系由该条件定义.所以在你的第一个例子中,你说这些表是相关的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);
Run Code Online (Sandbox Code Playgroud)

结果:

field1
200
Run Code Online (Sandbox Code Playgroud)

查询2(AND):

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

结果:

field1
100
200
Run Code Online (Sandbox Code Playgroud)

使用的测试数据:

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');
Run Code Online (Sandbox Code Playgroud)


Unr*_*son 6

SQL来自关系代数.

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

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


有关连接类型的概述,请再次阅读文章.

当我说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 =运算符,但这不是被其他供应商接受,也没有标准).

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


lex*_*exu 5

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

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