当前位置:  开发笔记 > 编程语言 > 正文

在JOIN和WHERE中过滤查询的区别?

如何解决《在JOIN和WHERE中过滤查询的区别?》经验,为你挑选了2个好方法。

在SQL中,我试图根据ID过滤结果,并想知道它们之间是否存在任何逻辑差异

SELECT value 
FROM table1 
JOIN table2 ON table1.id = table2.id 
WHERE table1.id = 1

SELECT value 
FROM table1 
JOIN table2 ON table1.id = table2.id AND table1.id = 1

对我来说,它好像逻辑是不同的,虽然你总是会得到相同的结果集,但我不知道是否有下,你会得到两个不同的结果集(或将它们总是返回完全相同的两个结果集的任何条件)



1> Pரதீப்..:

答案没有区别,但是:

我总是喜欢这样做.

始终保持Join Conditions in ON子句

始终将过滤器放在where子句中

这使查询更具可读性.

所以我将使用此查询:

SELECT value
FROM table1
INNER JOIN table2
        ON table1.id = table2.id
WHERE table1.id = 1

但是,当您使用时OUTER JOIN'S,将过滤器保持在ON条件和Where条件中会有很大的不同.

逻辑查询处理

以下列表包含查询的一般形式,以及根据逻辑处理不同子句的顺序分配的步骤编号.

(5) SELECT (5-2) DISTINCT (5-3) TOP() (5-1) 
(1) FROM (1-J)   JOIN  ON 
| (1-A)   APPLY  AS 
| (1-P)  PIVOT() AS 
| (1-U)  UNPIVOT() AS 
(2) WHERE 
(3) GROUP BY 
(4) HAVING 
(6) ORDER BY ;

流程图逻辑查询处理

在此输入图像描述

(1)FROM:FROM阶段标识查询的源表和进程表运算符.每个表运算符都应用一系列子阶段.例如,连接中涉及的阶段是(1-J1)笛卡尔积,(1-J2)ON滤波器,(1-J3)添加外行.FROM阶段生成虚拟表VT1.

(1-J1)笛卡尔积:此阶段在表运算符中涉及的两个表之间执行笛卡尔积(交叉连接),生成VT1-J1.

(1-J2)ON过滤器:此阶段根据ON子句中出现的谓词()过滤VT1-J1中的行.只有谓词计算为TRUE的行才会插入到VT1-J2中.

(1-J3)添加外围行:如果OUTER JOIN被指定(相于交叉连接或INNER JOIN),从保留的表或表中的行针对其匹配的未发现被添加到行从VT1-J2作为外行,生成VT1-J3.

(2)WHERE:此阶段根据WHERE子句()中出现的谓词过滤VT1中的行.只有谓词计算为TRUE的行才会插入到VT2中.

(3)GROUP BY:此阶段根据GROUP BY子句中指定的列列表将VT2中的行排列成组,生成VT3.最终,每组将有一个结果行.

(4)HAVING:此阶段根据HAVING子句()中出现的谓词过滤VT3中的组.只有谓词计算为TRUE的组才会插入到VT4中.

(5)SELECT:该阶段处理SELECT子句中的元素,生成VT5.

(5-1)计算表达式:此阶段评估SELECT列表中的表达式,生成VT5-1.

(5-2)DISTINCT:此阶段从VT5-1中删除重复行,生成VT5-2.

(5-3)TOP:此阶段根据ORDER BY子句定义的逻辑顺序过滤VT5-2中指定的最大行数或行百分比,生成表VT5-3.

(6)ORDER BY:该阶段根据ORDER BY子句中指定的列列表对VT5-3中的行进行排序,生成游标VC6.

它是从这个优秀的链接中提到的.


关于**可读性**的主题:我还建议与你的关键词保持一致** - 要么全部用大写字母,要么全部用小写字母,或者全部是大小写 - 我不是关心 - 但只是**一致** - 不要在同一个查询中使用一种风格(`SELECT`,`FROM`)与第二种风格(`on`,`where`)混合.... ..让它真的很难读懂那个T-SQL代码....选择一种风格 - 无论你喜欢什么 - 但随后**贴纸**并保持一致
同意并同意!此外,您的联接是_specific_.IE浏览器.在定义连接IMO时使用`INNER`或`LEFT-OR-RIGHT OUTER`.
虽然我同意这个SPECIFIC问题.当条件在有限匹配记录集上时,OUTER联接在限制标准的位置有很大差异.过滤器可以进入on子句,并且在某些情况下必须使用外部连接以获得所需的结果.或者你最终使用where子句(与圣诞老人条款不同),例如`(val ='blue'或val为null)`,这也可能产生不正确的结果,特别是如果NULL具有超出连接中生成的特定含义.

2> Stan Shaw..:

虽然使用INNER JOINS没有区别,正如VR46指出的那样,当使用OUTER JOINS并评估第二个表中的值时(对于左连接 - 右连接的第一个表),存在显着差异.请考虑以下设置:

DECLARE @Table1 TABLE ([ID] int)
DECLARE @Table2 TABLE ([Table1ID] int, [Value] varchar(50))

INSERT INTO @Table1
VALUES
(1),
(2),
(3)

INSERT INTO @Table2
VALUES
(1, 'test'),
(1, 'hello'),
(2, 'goodbye')

如果我们使用左外连接从中选择并在where子句中放入一个条件:

SELECT * FROM @Table1 T1
LEFT OUTER JOIN @Table2 T2
    ON T1.ID = T2.Table1ID
WHERE T2.Table1ID = 1

我们得到以下结果:

ID          Table1ID    Value
----------- ----------- --------------------------------------------------
1           1           test
1           1           hello

这是因为where子句限制了结果集,因此我们只包含table1中ID为1的记录.但是,如果我们将条件移动到on子句:

SELECT * FROM @Table1 T1
LEFT OUTER JOIN @Table2 T2
    ON T1.ID = T2.Table1ID
    AND T2.Table1ID = 1

我们得到以下结果:

ID          Table1ID    Value
----------- ----------- --------------------------------------------------
1           1           test
1           1           hello
2           NULL        NULL
3           NULL        NULL

这是因为我们不再通过table1的ID为1过滤结果集 - 而是我们正在过滤JOIN.因此,即使table1的ID为2 DOES在第二个表中有匹配,它也会从连接中排除 - 但不是结果集(因此为空值).

因此,对于内部联接并不重要,但是为了可读性和一致性,您应该将它保留在where子句中.但是,对于外连接,您需要注意,放置条件的位置很重要,因为它会影响结果集.

推荐阅读
大大炮
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有