首先, 准备数据, 地址是: https://github.com/cystanford/sql_heros_data, 除了id之外, 24个字段的含义以下:git
查询分为单列查询, 多列查询, 所有查询等等:github
SELECT name FROM heros; // 单列查询 SELECT name, hp_max, mp_max, attack_max, defense_max FROM heros; // 多列查询 SELECT * FROM heros; // 所有查询
学习阶段可使用SELECT *, 可是在生产环境不要用, 由于效率会很是低.sql
起别名是一种技巧, 能够对原有名称进行简化, 让SQL语句看起来更加精简, 这个在多表链接查询的时候很是有用:数据库
SELECT name AS n, hp_max AS hm, mp_max AS mm, attack_max AS am, defense_max AS dm FROM heros; // 起别名查询
SELECT 查询能够对常数进行查询, 简单说就是在SELECT查询结果中增长一列固定的常数列. 通常用于整合不一样的数据源, 用常数做为这个表的标记.网络
SELECT '王者荣耀' as platform, name FROM heros; // 查询常数
虚构了一个platform字段, 注意的是, 字符串常数要是用单引引发来, 不然会被当作列名来进行查询, 会报错, 若是是数字的话不须要添加单引号.学习
去除重复行是个很是少实用的操做, 关键字是DISTINCT:优化
SELECT DISTINCT attack_range FROM heros; SELECT DISTINCT attack_range, name FROM heros
须要注意的是:code
检索数据的时候, 能够按照某种顺序来进行结果的返回, 好比说查询全部的英雄, 按照最大生命从高到低的顺序进行排列, 这个时候排序就要使用到 ORDER BY 子句了, 注意点以下:orm
SELECT name, hp_max FROM heros ORDER BY hp_max DESC ; // 最大生命排序 SQL:SELECT name, hp_max FROM heros ORDER BY mp_max, hp_max DESC; // 最大法力升序, 法力相同, 生命值降序排序
约束返回结果的数量, 使用LIMIT关键字.blog
SELECT name, hp_max FROM heros ORDER BY hp_max DESC LIMIT 5; // 最大生命值从高到低排序并返回前五条数据
注意的是在不一样的DBMS中, 使用的关键字可能不一样. 在 MySQL、PostgreSQL、MariaDB 和 SQLite 中使用 LIMIT 关键字,并且须要放到 SELECT 语句的最后面。若是是 SQL Server 和 Access,须要使用 TOP 关键字
SELECT TOP 5 name, hp_max FROM heros ORDER BY hp_max DESC;
若是是 DB2,使用FETCH FIRST 5 ROWS ONLY这样的关键字
SELECT name, hp_max FROM heros ORDER BY hp_max DESC FETCH FIRST 5 ROWS ONLY;
若是是 Oracle,你须要基于 ROWNUM 来统计行数:
SQL:SELECT name, hp_max FROM heros WHERE ROWNUM <=5 ORDER BY hp_max DESC;
约束返回结果数量能够减小数据表的网络传输量, 能够提高查询效率.
这里要说的是两个顺序, 一个是关键字的顺序, 一个是SELECT语句的执行顺序:
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...
FROM > WHERE > GROUP BY > HAVING > SELECT 的字段 > DISTINCT > ORDER BY > LIMIT
一条SQL语句, 关键字顺序和执行顺序以下:
SELECT DISTINCT player_id, player_name, count(*) as num # 顺序 5 FROM player JOIN team ON player.team_id = team.team_id # 顺序 1 WHERE height > 1.80 # 顺序 2 GROUP BY player.team_id # 顺序 3 HAVING num > 2 # 顺序 4 ORDER BY num DESC # 顺序 6 LIMIT 2 # 顺序 7
在SELECT语句执行这些步骤的时候, 每一个步骤都会生成一张虚拟表, 而后将这个虚拟表传入下一个步骤做为输入. 可是这些步骤是隐含在SQL的执行过程当中, 对咱们是不可见的.
SELECT是先执行FROM这一步的, 这个阶段, 若是是多张表联查, 会经历下面的步骤:
两张以上的表, 会重复上面的步骤, 直到全部的表都被处理完成, 这个过程获得的最后结论就是如今的原始数据.
拿到原始数据以后, 就能够在这个基础上再进行WHERE阶段了. 这个过程会再次获得一个虚拟表,假设为vt2.
以后进入第三步和第四步, 也就是GROUP BY和HAVING阶段, 在vt2上进行分组和分组过滤, 获得中间的虚拟表vt3.
上面筛序就完成了, 接下来进入到SELECT阶段, 固然, 是先查询出所须要的列(字段), 以后就会进入到DISTINCT阶段, 这个也是两个阶段, 也会产生虚拟表.
字段选择并过滤重复以后就会进入到ORDER BY阶段进行排序, 再次获得虚拟表.
最后进入LIMIT阶段, 获得最终的结果.
在一条SQL中, 不存在的关键字, 中间的那部分阶段就会省略, 这些就是底层的原理.(疑惑是查询字段会使用到别名这些, 这些又是如何识别的呢?)
COUNT(*) = COUNT(1) > COUNT(字段), 因此尽可能使用COUNT(*)
,固然若是你要统计的是就是某个字段的非空数据行数,那另当别论。毕竟执行效率比较的前提是要结果同样才行。COUNT(*)
,尽可能在数据表上创建二级索引,系统会自动采用key_len小的二级索引进行扫描,这样当咱们使用SELECT COUNT(*)
的时候效率就会提高,有时候提高几倍甚至更高都是有可能的。