百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>数据库> 怎样写优雅的SQL原生语句
分享文章到:

怎样写优雅的SQL原生语句

发布时间:09/01 来源:未知 浏览: 关键词:
上一篇讲Mysql根本架构时,以"sql查询语句在MySql架构中概括是怎么施行的"进行了全面的解说。晓得了sql查询语句在MySql架构中的概括施行流程,但为了能够更好更快的写出sql语句,我觉得非常有须要晓得sql语句中各子句的施行次序

前言:

上一篇讲Mysql根本架构时,以"sql查询语句在MySql架构中概括是怎么施行的" 进行了全面的解说。晓得了sql查询语句在MySql架构中的概括施行流程,但是为了能够更好更快的写出sql语句,我觉得非常有须要晓得sql语句中各子句的施行次序。看过上一篇文章的小同伴应当都晓得,sql语句最后各子句的施行应当是在施行器中完成的,存储引擎对施行器供给的数据读写接口。此刻开端我们的学习

语句中各子句完备施行次序具体(按照次序号施行)

  1. from (注:这里也包含from中的子语句)

  2. join

  3. on

  4. where

  5. group by(开端运用select中的又名,背面的语句中都可以运用)

  6. avg,sum.... 等聚合函数

  7. having

  8. select

  9. distinct

  10. order by

  11. limit

每个子句施行次序剖析

所有的 查询语句都是从from开端施行的,在施行历程中,每个步骤都会为下一个步骤生成一个虚拟表,这个虚拟表将作为下一个施行步骤的输入。

1. from

form是一次查询语句的开始。

  • 要是是一张表,会直接操纵这张表;

  • 要是这个from背面是一个子查询,会先施行子查询中的内容,子查询的效果也就是首先个虚拟表T1。(注意:子查询中的施行流程也是按照本篇文章讲的次序哦)。

  • 要是需要关联表,运用join,请看2,3

2. join

要是from背面是多张表,join关联,会第一对前两个表施行一个笛卡尔乘积,这时候就会生成首先个虚拟表T1(注意:这里会选中相对小的表作为根基表);

3. on

对虚表T1进行ON筛选,只要那些相符的行才会被记载在虚表T2中。(注意,这里的这里要是还有第三个表与之关联,会用T2与第三个表进行笛卡尔乘积生产T3表,继续反复3. on步骤生成T4表,不外下面的次序解说临时不针对这里的T3和T4,只是从一个表关联查询T2继续说)

4. where

对虚拟表T2进行WHERE前提过滤。只要相符的记载才会被插入到虚拟表T3中。

5.group by

group by 子句将中的独一的值组合成为一组,得到虚拟表T4。要是利用了group by,那么背面的所有步骤都只能操纵T4的列或者是施行6.聚合函数(count、sum、avg等)。(注意:缘由在于分组后终究的效果集中只包括每个组中的一行。谨记,否则这里会涌现许多题目,下面的代码误区会特殊说。)

6. avg,sum.... 等聚合函数

聚合函数只是对分组的效果进行一些处置,拿到某些想要的聚合值,例如求和,统计数目等,并不生成虚拟表。

7. having

利用having筛选器,生成T5。HAVING子句主要和GROUP BY子句配合运用,having筛选器是首先个也是为独一一个利用到已分组数据的筛选器。

8. select

施行select操纵,选中指定的列,插入到虚拟表T6中。

9. distinct

对T6中的记载进行去重。移除雷同的行,发生虚拟表T7.(注意:事实上要是利用了group by子句那么distinct是余外的,缘由一样在于,分组的时候是将列中独一的值分成一组,同时只为每一组返回一行记载,那么所以的记载都将是不雷同的。 )

10. order by

利用order by子句。按照order_by_condition排序T7,此时返回的一个游标,而不是虚拟表。sql是基于汇合的理论的,汇合不会预先对他的行排序,它只是成员的逻辑汇合,成员的次序是无关大局的。对表进行排序的查询可以返回一个对象,这个对象包括特定的物理次序的逻辑组织。这个对象就叫游标。
oder by的几点注明

  • 由于order by返回值是游标,那么运用order by 子句查询不克不及利用于表表达式。

  • order by排序是很需要老本的,除非你必需要排序,不然最佳不要指定order by,

  • order by的两个参数 asc(升序罗列) desc(落序罗列)

11. limit

掏出指定行的记载,发生虚拟表T9, 并将效果返回。

limit背面的参数可以是 一个limit m ,也可以是limit m n,表示从第m条到第n条数据。

(注意:许多开发人员喜好运用该语句来解决分页题目。关于小数据,运用LIMIT子句没有任何题目,当数据量非常大的时候,运用LIMIT n, m是非常低效的。由于LIMIT的机制是每次都是从头开端扫描,要是需要从第60万行开端,读取3条数据,就需要先扫描定位到60万行,然后再进行读取,而扫描的历程是一个非常低效的历程。所以,关于大数据处置时,是非常有须要在利用层创立一定的缓存机制)

开发某需求写的一段sql

SELECT `userspk`.`avatar` AS `user_avatar`, 
`a`.`user_id`, 
`a`.`answer_record`, 
 MAX(`score`) AS `score`FROM (select * from pkrecord  order by score desc) as a 
INNER JOIN `userspk` AS `userspk` ON `a`.`user_id` = `userspk`.`user_id`WHERE `a`.`status` = 1 AND `a`.`user_id` != 'm_6da5d9e0-4629-11e9-b5f7-694ced396953' GROUP BY `user_id`ORDER BY `a`.`score` DESC LIMIT 9;

查询效果:

  • 先简要说一下我要查询的内容:

想要查询pk记载表中分数最高的9个会员记载和他们的头像。

  • 通过这段sql现实想一遍sql各字句的施行次序

pk记载表的数据构造设计,每个会员天天每个馆下可能会有多笔记录,所以需要进行分组,而且查询效果只想拿到每个分组内最高的那笔记录

这段sql的一些注明:

  1. 可能有些同窗会以为子查询没有须要 直接查询pk记载表就可以,但是并不克不及拿到预测的效果,由于分组后的每个组效果是不进行排序的,并且max拿到的最高分数确定是对应的该分组下最高分数,但是其它记载可能就不是最高分数对应的那笔记录。所以子查询非常有须要,它能够对原始的数据第一进行排序,分数最高的那条就是首先条对应的首先笔记录。

看一下代码和施行效果与带有子查询的进行比拼,就能了解我上面说的一段话:

//不运用子查询SELECT `userspk`.`avatar` AS `user_avatar`, 
`pkrecord`.`user_id`, 
`pkrecord`.`answer_record`, 
`pkrecord`.`id`, 
 MAX(`score`) AS `score`FROM pkrecordINNER JOIN `userspk` AS `userspk` ON `pkrecord`.`user_id` = `userspk`.`user_id`WHERE `pkrecord`.`status` = 1 AND `pkrecord`.`user_id` != 'm_6da5d9e0-4629-11e9-b5f7-694ced396953' GROUP BY `user_id`ORDER BY `pkrecord`.`score` DESC LIMIT 9;

查询效果

2. 在子查询中对数据已经进行排序后,外层排序方式要是和子查询排序分数雷同,都是分数倒序,外层的排序可以去除,没有须要写两遍。

sql语句中的又名

又名在哪些状况运用

在 SQL 语句中,可认为表名称及字段(列)名称指定又名

  • 表名称指定又名

同时查询两张表的数据的时候: 未设定又名前:

SELECT article.title,article.content,user.username FROM article, userWHERE article.aid=1 AND article.uid=user.uid

设定又名后:

SELECT a.title,a.content,u.username FROM article AS a, user AS u where a.aid=1 and a.uid=u.uid

益处:运用表又名查询,可以使 SQL 变得简约而更易书写和浏览,尤为在 SQL 比拼复杂的状况下

  • 查询字段指定又名

查询一张表,直接对查询字段设定又名

SELECT username AS name,email FROM user

查询两张表

益处:字段又名一个显明的结果是可以自定义查询数据返回的字段名;当两张表有雷同的字段需要都被查询出,运用又名可以完善的进行区分,以免冲突

SELECT a.title AS atitle,u.username,u.title AS utitle FROM article AS a, user AS u where a.uid=u.uid
  • 关联查询时候,关联表本身的时候,一些分类表,必需运用又名。

  • 又名也可以在group by与having的时候都可运用

  • 又名可以在order by排序的时候被运用

    查看上面一段sql

  • delete , update MySQL都可以运用又名,又名在多表(级联)删除尤其实用

delete t1,t2 from t_a t1 , t_b t2 where t1.id = t2.id
  • 子查询效果需要运用又名

    查看上面一段sql

又名运用注意事项

  • 虽然定义字段又名的 AS 关键字可以省去,但是在运用又名时候,倡议不要省去 AS 关键字

书写sql语句的注意事项

书写标准上的注意

  • 字符串类型的要加单引号

  • select背面的每个字段要用逗号分隔,但是最后连着from的字段不要加逗号

  • 运用子查询新建暂时表的时候要运用又名,不然会报错。

为了加强机能的注意

  • 不要运用“select * from ……”返回所有列,只检索需要的列,可以免后续因表构造变化致使的无须要的程序修改,还可落低额外耗损的资源

  • 不要检索已知的列

select  user_id,name from User where user_id = ‘10000050’
  • 运用可参数化的搜寻前提,如=, >, >=, <, <=, between, in, is null以及like ‘%’;尽量不要使用非参数化的负向查询,这将导致无法使用索引,如<>, !=, !>, !<, not in, not like, not exists, not between, is not null, like ‘%’

  • 当需要验证可否有相符前提的记载时,运用exists,不要运用count(*),前者在首先个匹配记载处返回,后者需要遍历所有匹配记载

  • Where子句中列的次序与需运用的索引次序维持一致,不是所有数据库的优化器都能对此次序进行优化,维持良好编程习惯(索引相干)

  • 不要在where子句中对字段进交运算或函数(索引相干)

  1. 如where amount / 2 > 100,即便amount字段有索引,也没法运用,改成where amount > 100 * 2就可运用amount列上的索引

  2. 如where substring( Lastname, 1, 1) = ‘F’就没法运用Lastname列上的索引,而where Lastname like ‘F%’或者where Lastname >= ‘F’ and Lastname < ‘G’就可以

  • 在有min、max、distinct、order by、group by操纵的列上建索引,以免额外的排序开销(索引相干)

  • 当心运用or操纵,and操纵中任何一个子句可运用索引都会提高查询机能,但是or前提中任何一个不克不及运用索引,都将致使查询机能下落,如where member_no = 1 or provider_no = 1,在member_no或provider_no任何一个字段上没有索引,都将致使表扫描或聚簇索引扫描(索引相干)

  • Between个别比in/or高效得多,要是能在between和in/or前提当选择,那么始终选中between前提,并用>=和<=条件组合替代between子句,因为不是所有数据库的优化器都能把between子句改写为>=和<=条件组合,如果不能改写将导致无法使用索引(索引相关)

  • 调整join操纵次序以使机能最优,join操纵是自顶向下的,尽量把效果集小的两个表关联放在前面,可提高机能。(join相干) 注意:索引和关联我会独自拿出来两篇文章进行细致解说,在这个注意事项中只是简略提一下。

更多MySQL相干技术文章,请拜访MySQL教程栏目进行学习!

以上就是怎样写优雅的SQL原生语句的细致内容,更多请关注 百分百源码网 其它相干文章!

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有154人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板