回答

收藏

MySQL语句中过滤条件放在哪?on、where还是having,他们区别和联系(mysql过滤空数据)

知识点 知识点 34 人阅读 | 0 人回复 | 2023-01-19

帖子摘要:SQL语句中过滤条件放在不同筛选器on、where和having的区别和联系。  蚂蚁金服的一道SQL面试题如下SQL语句中过滤条件放在on和where子句中的区别是什么 当时满脑子是left joi......
0 F7 {$ i2 e- r( n. h6 @, \7 o! B2 |, s# l
大家好,欢迎来到Java吧(www.java8.com),交流、学习Java技术、获取Java资源无任何套路,今天说一说:“MySQL语句中过滤条件放在哪?on、where还是having,他们区别和联系”0 W* y) {& N4 [3 v  c) I
) s; |2 Y6 s. e

: e, r# S7 ^' E4 O& E        : ]2 `! i  L5 u) i
               
. N* w! u4 H! V+ q                    ' P! `7 g8 g  h  J
                        
" Q! S! P$ G/ ]% l                    
/ i. C+ D( E( e3 m0 @, d1 h" I  h                     $ n( a3 [7 v7 u! p! B- K
SQL语句中过滤条件放在不同筛选器on、where和having的区别和联系。
5 l% X' I) ~2 f; K
0 ^' I. _+ w3 g( c# N. h6 S9 e
+ x# S, n* J. f$ m4 e
蚂蚁金服的一道SQL面试题如下SQL语句中过滤条件放在on和where子句中的区别是什么 当时满脑子是left join和inner join等觉得没区别啊当天晚上细思极恐故梳理一下。9 t6 ~" z+ s' x& P5 R7 A
+ f$ G% O0 i: s: S9 g5 E; q
在多表连接查询语法中最令人迷惑的非on和where这两个筛选器的区别莫属了。在编写查询SQL脚本的时候筛选条件无论是放在on子句还是where子句查询到的结果集总是一模一样的既然如此为什么还要让sql查询支持两种筛选器呢这不是多此一举吗其实这两种筛选器在执行效率方面存在差异只是如果不深度挖掘不容易发现罢了。
; E4 }9 q. Y+ r- b& E/ D
3 [; S' a5 F6 J  C5 m! k过滤条件放在on和where中的区别   W' e* k2 ^" S
数据库在通过连接两张或多张表来查询记录时都会先通过join on子句生成一张中间的临时表然后再在临时表中通过where子句过滤数据并将结果集返回给用户。在使用多表关联时on和where子句的区别如下# K/ U$ t7 J, W, l% c  ^! n

& W6 I- J) Z' y6 f
. _+ F# g; X3 e 1、 on子句是在生成临时表时使用的。它不管on中的条件是否为真都会返回驱动表中的记录被驱动表成立就返回对应数据不成立就赋值为null。$ |" W' d! W; }* O) m6 u. V) Y
. C" N- }/ ~8 E/ D1 e- ?9 s. X
通俗地说 对于左外连接left join或者右外连接right join的驱动表来说如果无法在被驱动表中找到匹配
  1. ON
复制代码
子句中的过滤条件的记录那么该记录仍然会被加入到结果集中对应的被驱动表记录的各个字段使用
  1. NULL
复制代码
值填充。" |* B/ e0 [& Q3 i/ v/ {5 i/ t7 o! P" t

4 L' W1 i9 b) D* s3 U 2、where子句是对已经生成的临时表进行过滤的条件这时过滤临时表中全部条件不为真的记录。
0 I$ o8 H5 `0 T. m4 x8 A $ L7 G8 ]# p, ], W

1 I% D! `' L  N, [需要注意的是内连接中的WHERE子句和ON子句是等价的。
  1. ON子句
复制代码
是专门为外连接驱动表中的记录在被驱动表找不到匹配记录时应不应该把该记录加入结果集这个场景提出的所以如果把
  1. ON子句
复制代码
放到内连接中
  1. MySQL
复制代码
会把它和
  1. WHERE子句
复制代码
一样对待。$ ]0 y' ~) u4 ]: W
, i9 k8 S8 b, N* s+ d# }; D! Z6 o
在使用 INNER JOIN 时会产生一个结果集WHERE 条件在这个结果集中再根据条件进行过滤如果把条件都放在 ON 中在 INNER JOIN 的时候就进行过滤了比如
; N" O( f! a, y+ [2 O
% N- l  z- [+ `. h
  1. SELECT A.* FROM A * B  X1 M, |5 k( G1 i4 I
  2. INNER JOIN B ON B.ID = A.ID AND B.State = 1 -- on子句可以写多个条件
  3. INNER JOIN C ON B.ID = C.ID 2 |" G% w' A2 H/ z: }" C1 ~; g5 P
复制代码
( ?. \" G% Z0 v
在联查 B 表时就过滤掉状态不等于 1 的记录从而使得状态不等于 1 的记录就不需要去联查 C 表了而: a" r8 R6 [6 P: }
5 C8 v* L1 D7 b. ?! f4 f
  1. SELECT A.* FROM A 9 v) C5 m1 s! D  P7 L' B$ R+ w4 ?
  2. INNER JOIN B ON B.ID = A.ID + f3 x/ g- B0 x- O, o2 V, s
  3. INNER JOIN C ON B.ID = C.ID
  4. WHERE B.State = 1
复制代码
2 G. d) x# Q1 v# w2 r
则不考虑 B 的状态是否满足都去联查 C生成临时表最后再通过where子句将满足B 状态State = 1的记录查出来。综上所述得出的结论就是把 过滤条件放入inner join on 比直接 where 的查询效率要高
0 R/ l4 N, i; Y' _, M! @, o5 |# | 5 R4 z9 J# Z, J8 S6 J" B1 J6 `
on、where、having的区别和联系 8 ]1 c4 f! s( z' z4 U6 h
在写SQL语句的时候我们经常会用到各种表连接left join、right join、inner join和 full join等还有各种分组聚合函数sum、min、max、avg和count等。那么我们在写连接操作SQL的时候对于不同的过滤条件是放在 ON 子句还是代表分组操作的 having 子句抑或 where子句中呢我们先看一下三种条件关键字的执行顺序3 _- l4 x! z/ Z

9 z  b, g- `, S, E ! i2 B+ J0 \4 j2 k
on > where > 聚合函数 > having5 o/ Q5 U# p! T: k

4 d9 @( Z) R- g* p4 w
5 E% X. ^( Z6 \' @
详细的来讲就是
2 z# J8 t; Y) } $ N" R' I0 ]8 v9 x3 W
步骤一、根据on筛选器生成生成临时表。此时的临时表会因为left join或right join的特性而一定带有主表的记录也就是主表的记录不会被 on 条件过滤掉。3 v2 i- x; D/ W3 S

" V6 N* Q+ b4 |' t' U- j% A步骤二、根据where筛选器过滤临时表。因为临时表已经生成完毕根据where条件过滤时主表记录也会被过滤。& D. m& R8 G: f% Q
7 b' r( G0 O) Q+ q  X/ }' U
步骤三、聚合函数进行运算。
, ~( Q: q) s6 _+ A: F: N9 ^: Z
1 b9 ~/ c2 O' N, R; v, K6 l步骤四、 聚合函数运算完毕having子句生效对运算完毕的临时表进行过滤 生成最终的结果表。8 L- u$ R% ^6 p

& V" E! f5 R$ b& X三个筛选器on、where和having都可以加条件on是最先执行where次之having最后。有时候如果这先后顺序不影响中间结果的话那最终结果是相同的。但因为on是先把不符合条件的记录过滤后才进行统计它就可以减少中间运算要处理的数据按理说应该速度是最快的。
# M/ A& J, z/ z; |$ N* g , ^$ ^9 ~+ @, ^; L! b& L7 e( m
了解了上述执行过程后我们来聊聊应该把过滤条件放在哪即如何使用on、where和having筛选器。下面是一些基础的选择标准供各位参考/ O  P8 r  I- k1 J9 x* q
- s  S0 ^" S2 ^# Z. _

7 p/ A+ f% Z6 j# a" W8 o( u [ol]
  • 所有的连接条件都必需要放在ON子句。
  • 如果在表关联后需要保留主表的所有记录不论有没有相匹配的从表记录那么我们就应该将过滤条件放在 on 中。
  • 如果过滤条件需要在聚合函数运算完毕之后才能确定比如我们想要找出平均分数大于60分的班级那么就必须等待分组聚合函数执行完毕才能进行过滤那这个过滤条件肯定就是放在having中了因为where生效的时候聚合函数还没有进行运算。
  • 如果过滤条件不依赖聚合函数只是想要符合条件的部分记录而且没有要求保留主表的全部记录那么我们就应该放在where子句中。当然如果表关联是采用inner join的话因为没有主从表的关系所以放在 where 和 on 中是一样的。
  • 就执行效率来看因为on生效最早所以放在on中应该最快其次是where最后是having。[/ol]
    * O* _( F7 D6 j, C( R

    * @' g) W9 J! g: p3 A0 u0 ]* S                0 G) q( E5 e& J! a' E
                   
    + \9 U6 M) H1 ^( d                # e2 n' Z1 D0 F0 Q. t9 R
    本文来源csdn,由Java吧转载发布,观点不代表Java吧的立场,转载请标明来源出处:https://www.java8.com
  • 分享到:
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则