MySQL 查询操作

mysql中查询的关键字是SELECT,其完整语法为:(下面会分别介绍每个段的用法,可以先看后面的再回过头看前面)

SELECT
DISTINCT <select_list>
FROM <left_table>
<join_type> JOIN <right_table>
ON <join_condition>
WHERE <where_condition>
GROUP BY <group_by_list>
HAVING <having_condition>
ORDER BY <order_by_condition>
LIMIT <limit_number>

要提一下的是,为了高效操作,一条语句中每步的操作都会产生一个虚表,下一步即对这个虚表进行操作,虚表会在内部自动生成和删除。

查询语句很多时候绕的晕,其实是你不熟悉每条语句的执行顺序。在引擎内部的语句执行的顺序和语法写的顺序是不一样的,下面看看select机器内部的执行顺序:

1. FROM  <left_table>             #先对表进行笛卡尔乘积,得到虚表T1
2. ON <join_codition>             #对T1进行条件筛选,得到T2
3. <join_type> JOIN <right_table> #根据连接类型,对T2进行信息补充,比如left join,左边表未匹配到的部分会适当添加NULL后加入到T2中,形成T3
4. WHERE <where_condition>        #对T3进行筛选,得到T4
5. GROUP BY <group_by_list>       #根据要分组的列,对T4进行分组,得到T5
6. HAVING <HAVING_condition>      #对T5进行筛选,得到T6
7. SELECT                         #这时才选择列,选择T6中指定的列,得到T7
8. DISTINCT <select_list>         #对T7除重 得到T8
9. ORDER BY <order_by_condition>  #对T8 进行排序 得到T9
10. LIMIT <limit_number>          #对T9进行截取,得到最终结果

基本查询

查询表中的某列,多个列名可以用逗号分隔,所有列可以用 * 代替,语法:

SELECT list_name1,list_name2 … FROM table_name;
eg:SELECT * FROM students; #查看学生表

选择性查询

选择性的查询记录,通过where子句,进行字段的精确筛选。语法如下:

SELECT * FROM table_name WHERE <条件表达式>;
eg: SELECT * FROM students WHERE score >= 80 AND gender = 'M';

除了可以用<>=等运算符进行筛选,还可以使用BETWEEN,如where score BETWEEN 0 AND 60;筛选不及格记录。

用于where条件组合的四个操作符:AND、OR、IN、NOT。

IN用来指定条件范围,符合的条件都在括号内用逗号隔开,如where score IN(100,60);可以筛选满分和刚好及格的记录。IN比OR快。NOT用于否定条件,如前面语句改为NOT IN,筛选的就是及格的记录。

筛选过滤还可以采用通配符,关于LIKE、正则表达式见 MySQL 其他常用语法

子查询

查询可以嵌套,即可以查询另一个查询的结果。

SELECT * FROM (
    SELECT * FROM students
    WHERE scour<60
)   WHERE gender='M';

上面的语句当然可以用1条select完成,这里只是展示其用法。当业务需求复杂时,如从多个表获取信息时,子查询是十分灵活的选择。

聚合查询

使用聚合函数进行对数据汇总的查询。聚合函数有5个,COUNT、SUM、AVG、MAX、MIN。

比如统计一张表符合筛选条件的记录数,用COUNT()函数。格式为COUNT([DISTINCT|ALL] <列名>),DISTINCT表示不统计重复项,默认为ALL统计重复项。

SELECT COUNT(*) num FROM students;                           统计表中记录条数,返回一个2*1的二维表,字段名为num
SELECT COUNT(id) boys FROM students WHERE gender = 'M';      where执行在select之前,因此count统计的是筛选后的数据,结果如下

·count():count(list)统计list不为null的记录数;count(*)统计所有的记录数,null也会被统计,因为主键不会为null,相当于统计主键个数。

·avg()、sum()、max()、min():需要指定列名,也会忽略null。

分组查询

用GROUP BY对查询结果按字段列表进行分组,字段值相等的记录分为一组;语法如下:

[GROUP BY 字段列表] [HAVING <条件表达式>],HAVING用于过滤组,仅输出满足条件的组。

使用分组需要注意:

· NULL也会作为一个分组返回。

· GROUP BY中列出的每个列只能是检索列或有效表达式,不能是聚集函数。

· 除了聚集函数外,SELECT中列出的每个列也都必须在GROUP BY中列出。

比如现在想知道每个班的人数,可以这样做:

SELECT COUNT(*) num FROM students GROUP BY class_id;                  按班级分组,count是对每组进行计数        
SELECT class_id, COUNT(*) num FROM students GROUP BY class_id;   可以把class_id列也放入结果集
查出每个班级的平均分,并只看平均分高于80的班级,语句如下,结果如图:
SELECT class_id, AVG(score) avgscore FROM students GROUP BY class_id HAVING AVG(score)>80; 

 having和where不同,where是过滤记录,having是过滤组,where在分组前就过滤完,having在分组后过滤。

多表查询

mysql还可以同时查询多个表,得到的结果整合到一张表里,即students表的每一行与classes表的每一行都两两拼在一起返回。结果集的列数是students表和classes表的列数之和,行数是students表和classes表的行数之积。这种查询叫笛卡尔查询,又称交叉查询。

SELECT * FROM students, classes;

一般这样查询的结果,很多记录是没有意义的。如上语句,如果没有筛选,那么会出现小明既在一班又在其他班的记录,这明显是错误的。多表查询,表之间肯定是有某种联系联合起来才有意义,因此多表查询一般必须添加联结条件。上例中,学生表和班级表的联系就是class_id,正确的写法:

SELECT s.name name,gender,c.name classname from students s,classes c where s.class_id=c.id;

连接查询

很多时候多张表之间是有联系的,它们可能有相同的列,因此可以联结多个表进行查询。连接查询也是多表查询,通常使用多表查询时优先用连接查询,而不是上面介绍的多表查询。

语法:SELECT <列> FROM <表1> JOIN <表2> ON <条件...>;

连接的规则有两种:

· 内连接INNER JOIN:join前加inner关键字,不加的话,默认join也为内连接。返回笛卡尔积中符合连接条件的数据行,和上述的多表查询是一样的,不过SQL推荐使用联结写法,这样能避免忘记填写筛选条件。

· 外连接:又分三种;

  · 左连接LEFT OUTER JOIN:通过ON条件筛选后,将左表中其余未在结果中展示的记录也添加进来,空的字段补NULL。

  · 右连接RIGHT OUTER JOIN:类似左连接,补齐右表中的所有记录。

  · 全连接FULL OUTER JOIN:左表和右表的所有行数据都补齐,空的地方填NULL。

其中INNER和OUTER关键字可以省略,但使用全连接时不能省略。

值得注意的是,如果没有ON筛选,那么结果就是笛卡尔积。

内连接和上述多表连接产生相同效果,下面举例理解一下外连接,假如新学期开学了,二班的同学都毕业了,学校撤销了二班,并且新增了一个五班,有两名同学在五班念书,学校的管理混乱,只更新了students表。此时students表如下:

classes表如下:

 此时我们如果想将班级信息和学生信息统计在一张表,如果使用内连接,筛选条件为students.class_id=classes.id,那么新入学的柯基和二哈就不会显示。此时如果使用外连接,可以选择补齐哪个表的未匹配记录。

左连接
SELECT
students.name,gender,classes.name FROM students LEFT JOIN classes ON students.class_id=classes.id;
#一个表不允许重复的列名,因此将class的name重命名为classname;
#由下图可以看到,前7条记录是由ON筛选出来的,后两条是因为left join额外补齐的。

那么右连接和全连接的结果就很容易能想到了。

组合查询

组合查询通过UNION将多个SELECT查询结果组合到一张表中返回。

语法:SELECT … FROM … UNION SELECT … FROM … ORDER BY … LIMIT … ;

值得注意的是:

· 组合的两个select表需要有相同的列,聚合函数和表达式,不过它们的列可以顺序不同;

· 列的类型必须兼容,不必完全相同,但必须是可以隐式转换的类型。例如TINYINT和INT;

· 默认组合会去除重复的记录,即两个表中都有的记录。可以通过在UNION后加ALL关键词显示重复记录;

· ORDER是对组合后的结果进行排序,只允许有一个ORDER,且必须在最后。

排序

查询的结果集通常是按照表中实际存放顺序排序的,但可以自定义条件排序。通过ORDER BY命令可以指定通过什么字段排序,比如通过score排序:

SELECT * FROM students ORDER BY score;

默认是按照升序排序,也可以指定为降序ORDER BY score DESC;

可以对多列进行排序,即第一个排序条件相同时,比较后面的排序条件;

如果有WHERE子句,ORDER子句要放到其后面,逻辑上就是在筛选出的记录中排序。

分页

数据太多可以分页查看,M表示最多显示M条记录,N表示偏移量。LIMIT永远在语句最后,其语法是:

LIMIT <M> OFFSET <N>;
eg:SELECT * FROM students LIMIT 3 OFFSET 6;  表示显示3条记录,偏移6条记录,从第7条记录开始
还可以省略offset写成:LIMIT m,n; 表示偏移m条显示n条

 

 参考:廖雪峰的SQL教程 、《MySQL必知必会》

posted @ 2020-05-29 14:48  Glaci  阅读(269)  评论(0编辑  收藏  举报