一、如何理解SQL。
关于sql,俺觉得最最基础的是,你是在按什么角度去思考它。我倒是有一种方式,一看到select,就把从这个select到结束看成一个表,有多少select就有多少个表,然后这些表经过各种关系运算,最后得到你想要的结果,当然这个结果还是个表。
二、执行顺序
然后第二重要的是,你要理解sql的执行顺序,看到一个sql语句时,不要先从select看,亲,要先看from嘛,因为计算机就是这么干的。计算机先看from后面跟的是什么,比如from a,b,就把a和b的数据加载进内存,这个可是a(m条数据)和b(n条数据)的笛卡尔积啊,有m*n条数据。所以呢,使用form a left join b on a.id = b.id,会先pass一部分数据哦,这样加载进内存的数据量变小了,速度就上去了。 当你说,from a,b where a.id=b.id这不也过滤了吗。过滤是过滤了,只不过是加载进内存之后,才根据where条件过滤的。
执行顺序如下:
FROM
WHERE
GROUP BY
HAVING
SELECT
DISTINCT
UNION
ORDER BY
看见没,select t.x+t.y z from t where z=10是会报错滴,仅仅是因为where会在select前执行哦~
三、表连接
真是值得大说特说呢,因为sql中最难的就是select,select干的最多的就是表连接喽。咱一点一点说
(1)from a,b 与 union(union属于集合操作,但是我觉得放在这里对比挺有趣的)
a,b就是把表横着连在一起
比如‘表a’
ID | NAME |
1 | 夏娜 |
2 | 黄泉 |
表b
ID | name |
1 | 泰兰德 |
2 | 艾露恩 |
from a,b会得到
ID | NAME | ID | name |
1 | 夏娜 | 1 | 泰兰德 |
2 | 黄泉 | 2 | 艾露恩 |
1 | 夏娜 | 2 | 艾露恩 |
2 | 黄泉 | 1 | 泰兰德 |
而select * from a union select * from b会得到
ID | NAME |
1 | 夏娜 |
2 | 黄泉 |
1 | 泰兰德 |
2 | 艾露恩 |
最后提一嘴,union是去重的,不想去重用union all
join会把不满足的都干掉,只留下满足条件的。
outer join会把主表的都留下,驱动表有满足的就跟主表的这条数据连在一起(横着),某条主表数据在驱动表里没有找到满足条件的,就拿null跟这个主表数据拼在一起。left join左边是主表。right join右边是主表。full outer join大家互为主表和驱动表。
(3)半连接之in和exists
select name from a where id in(select id from b)
是这么执行的,把a表加载进内存,然后把b表加载进内存,把b表的id都取出来保存在内存(缓存?)中,取a的第一条数据,看id等于1或者2吗,满足则返回true,然后把这条数据存入虚表 。然后扫描a的第二条数据,进行比较。如果a这个表足够大,你就惨兮兮了,因为它要从头扫到尾,每次都做个判断(判断可是要时间成本的)。
select name from a where exists (select null from b where b.id = a.id)
首先exists里面的数据不会被保存在缓存里。它是这么执行的,取出a的一条数据,去跟b里的每一条进行比较判断(时间成本),满足则返回true,把刚才那条a的数据保存下来。正因为是逻辑判读所以exists里面select null也是可以的啦。发现没有,如果b表的数据量很大,你就惨了啊。跟in对比着看,发现什么了木有。
(4)反连接之not in和not exists
没什么好说的吧,记住not in()括号里面不要有null,因为任何东西一跟null比较就会获得false,这样你就啥都查不到了。但是在in()里面使用null是没有影响的,想想为什么,很简单的逻辑问题。
(5)交叉连接之cross join
跟逗号连接是一个东西。
四、group by
请看下表C
ID | NAME | WEAPON |
1 | 夏娜 | 太刀 |
2 | 黄泉 | 太刀 |
3 | 泰兰德 | 弓箭 |
果然赤裸裸的报错了,报错什么没有使用组函数啦。
为什么呢?亲,你模仿计算机弄出来个表给我看看呗。
ID | NAME | WEAPON |
1 | 夏娜 | 太刀 |
2 | 黄泉 | 弓箭 |
3 | 泰兰德 |
可以这样,select max(id),max(name),weapon from c group by weapon这样不报错了,但是数据是啥样子的自己想想。
五、语法顺序
select(对数据处理)
from(数据源:表)
where(选择操作:过滤记录)
group by(分组)
having(过滤组)
union(集合)
order by(排序)
有次面试,我就把语法顺序给写错了。啥也不说了。