MySQL数据查询SQL

MySQL数据查询SQL

SQL查询语句:SELECT

先给出一张表

在这里插入图片描述

检索数据select


检索单个列

select 字段 from tbname;
# 例: select name from stu;

如果没有明确排序规则,则返回的数据的顺序,则返回的数据的顺序没有特殊意义。

返回数据的顺序可能是数据被添加到表中的顺序,也可能不是 。只要返回相同的数目,就是正常的。

检索多个列

select 字段1,字段2,... from tbname;
# 例: select id,name,age,sex from stu;

在选择多个列时,一定要在列名之间加上逗号,但最后一个列名后面不加。

如果在最后一个列名后加了逗号会出现错误。

检索所有列

select * from tbname;
# 例: select * from stu;

一般不使用通配符,除非确实需要表中的每个列,否则最好别使用*通配符。

使用通配符可以检索出名字未知的列

检所不同行的DISTINCT

select distinct 字段1,字段2... from stu;
# 例: select distinct class_id from stu;

DISTINCT关键字只返回不同的值,若列里有很多个a和很多个b这两种值,只返回a和b

在这里插入图片描述

限制结果 LIMIT

select * from tbname limit 3,4;
# 代表从第三行开始检索,检索四行数据
# 代替的语法: limit 4 offset 3 意为从行3开始检索四行,和上面一样
# 例: select * from stu limit 3,4;

在这里插入图片描述

使用完全限定的表名

select name from stu;
select stu.name from stu;
select stu.name from demoDB.stu;

对检索数据进行排序 ORDER BY


排序数据 ORDER BY

select * from tbname order by 字段;

默认查询出的数据,并不是随机排序的,如果没有指定排序规则,数据一般将以它在底层表中出现的顺序显示

关系数据库设计理论认为,如果不明确规定排序顺序,则不应该假定检索出的数据的顺序有意义

通常,ORDER BY字句中使用的列将是为显示所选择的列。

但实际上并不是一定要这样,用非检索的列排序数据是完全合法的。

按多个列排序

select * from tbname order by 字段1,字段2,...;

在需要对多列数据进行排序时,用逗号分隔开列名,会按照前后顺序依次对比排序,默认为升序

select * from tbname order by 字段1(desc),字段2(desc),...;

对指定列名进行升序或降序排列,如 select * from stu order by class_id,age desc; 先对class_id做升序排列再对age进行降序排列

注意

ORDER BY 子句的位置给出ORDER BY子句时,应该保证它位于from子句后。

如果使用LIMIT,他必须位于ORDER BY子句完成后。使用子句的次序不对将产生错误信息。

数据检索条件过滤WHERE


数据库一般包含大量的数据,很少需要检索表中所有行。

通常只会根据特定操作或报告的所需要提取表数据的子集。

只检索所需数据需要制定搜索条件

select 字段 from tbname where 条件; 

同时使用 where 和 order by 时,where 应在前,order by 在后

WHERE子句操作符

操作符 说明
= 等于
<> 、!= 不等于
< 小于
<= 小于或等于
> 大于
>= 大于或等于
BETWEEN … and … 指定两个值之间
IS NULL 空值

组合WHERE子句

MySQL允许给出多个WHERE子句。

两种方式:AND和OR连接两个子句。也称逻辑操作符。

AND

AND用在WHERE子句中,用于检索必须符合and连接的所有条件才返回。否则返回 empty set

select 字段 from tbname where 字段=.. and 字段=..;
# 例:
select name from stu where age = 22 and sex = 'm';

OR

OR用在WHERE子句中,用于检索只需满足or连接的其中之一条件即可返回。否则返回 empty set

AND和OR可以连用,但必须注意SQL的计算次序,SQL在处理OR操作符前,会优先处理AND操作符

例如:查询一班和二班的女学员。

select * from stu where class_id=1 or class_id=2 and sex='女';

用这种方法就会出现下述情况
在这里插入图片描述

因为优先处理AND的机制,使得SQL认为需要查询的是二班的女生和一班的全体学生。

解决方法如下:

select * from stu where class_id=1 and sex='女' or class_id=2 and sex='女';
# 或者
select * from stu where (class_id=1 or class_id=2) and sex='女';

括号优先于and。

IN 和 NOT

IN

IN操作符用来指定条件范围,范围中每个条件都能进行匹配。可以与AND和OR连用

select name from stu where class_id in (1,2) and sex='女';

为什么要使用IN操作符?其优点如下:

  • 在使用长的合法选项清单时,IN操作符的语法更清楚且更直观。
  • 在使用IN时,计算的次序更容易理解(因为操作符少)
  • IN操作符一般比OR操作符清单执行更快
  • IN的最大优点是可以包含其他SELECT语句,使得能够更动态地建立WHERE子句。

NOT

NOT操作符用来指定除了此条件外的所有数据。

select name from stu where class_id not in (1);

通配符的使用

LIKE与通配符

LIKE 适用于模糊搜索,例如搜索产品名中包含文本 a 的所有产品。

  • 百分号(%)通配符,在搜索中 % 表示任意字符出现任意次数。

    select name from stu where name like 'a%'; # 表示匹配第一个字符为a的所有数据
    select name from stu where name like '%a'; # 表示匹配最后一个字符为a的所有数据
    select name from stu where name like '%a%'; # 表示匹配包含字符a的所有数据
    
  • 下划线(_)通配符,在使用下划线时,一个下划线等于一个字符。

    select name from stu where name like '_a';# 表示匹配最后一个字符为a且总长度为两个字符的数据
    select name from stu where name like 'a_';# 表示第一个字符为a且总长度为两个字符的数据
    

使用通配符的技巧

  • 不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。
  • 在确实需要使用通配符时,除非绝对必要,否则不要把它们放在开始处,如’%a’。把通配符放在开始处,搜索速度是最慢的。
  • 注意通配符位置。

正则REGEXP

select name from stu where name regexp '[0-5]abc'; # 第一个字符为0-5,后面为abc的所有数据

MySQL中的统计函数(聚合函数)

聚核函数的使用

我们经常需要汇总数据而不用把他们实际全部检索出来,为此MySQL提供了专门的函数。

使用这些函数,MySQL查询可用于检索特定数据,分析并形成报表。

比如:

  • 确定表中行数
  • 获得表中列的和。
  • 找出表列(或所有行、某些特定的行)的最大值、最小值、平均值。
函数 说明
COUNT() 返回某列的行数
MAX() 返回某列的最大值
MIN() 返回某列的最小值
SUM() 返回某列值的和
AVG() 返回某列的平均值

注意:

使用count时,如果指定列名,则指定列的值为空(NULL)的行被忽略,但如果函数中用的星号(*),则不忽略。

GROUP BY & HAVING

GROUP BY

SQL聚集函数可用来汇总数据。这是我们能够对行进行技术,计算和与平均数,获得最大最小值而不用检索所有数据。

目前为止,所有的计算都是在表的所有数据或匹配特定的WHERE子句的数据上进行。

但接下来我们可以使用group by…having的方式来实现分组后的再次过滤。

例如:我们需要获取所有班级的学员数量

mysql> select class_id,count(*) as nums from stu where class_id=1;
+----------+------+
| class_id | nums |
+----------+------+
|        1 |    6 |
+----------+------+
1 row in set (0.00 sec)

mysql> select class_id,count(*) as nums from stu where class_id=2;
+----------+------+
| class_id | nums |
+----------+------+
|        2 |    4 |
+----------+------+
1 row in set (0.00 sec)

我们需要查询两次。

但假如我们需要查询一所学校每个班级的人数,这种方法显然不合适,我们应该怎么办?

此时就需要进行分组了,sql分组允许把数据分为多个逻辑组,以便能对每个组进行聚集计算(group by)。

语法:select 字段, function(*) as 列名 from tbname group by 字段;

mysql> select class_id,count(*) as nums from stu group by class_id;
+----------+------+
| class_id | nums |
+----------+------+
|        1 |    6 |
|        2 |    4 |
+----------+------+
2 rows in set (0.00 sec)

如果想让系统返回一个人数少于5人的班级或者人数大于5人的班级该怎么办?

就要从上面的返回结果中进行再次筛选,也就是下面的HAVING过滤分组

HAVING

除了能用GROUP BY分组数据之外,MySQL还允许过滤分组,规定包括那些分组,排除那些分组。

例如上面所说的让系统返回一个人数少于5人的班级

事实上,之前所讲的WHERE子句都可以用HAVING代替,唯一的区别便是WHERE过滤行HAVING过滤分组

语法:语法:select 字段, function(*) as 列名 from tbname group by 字段 having 条件;

# 大于五人的班级
mysql> select class_id,count(*) as nums from stu group by class_id having nums>5;
+----------+------+
| class_id | nums |
+----------+------+
|        1 |    6 |
+----------+------+
1 row in set (0.00 sec)

# 小于五人的班级
mysql> select class_id,count(*) as nums from stu group by class_id having nums<5;
+----------+------+
| class_id | nums |
+----------+------+
|        2 |    4 |
+----------+------+
1 row in set (0.00 sec)

注意事项

假如现在需要增加一条字段class_name,用来储存班级名,筛选class_id、class_name和人数

mysql> select class_id,count(*) as '数量' from stu group by class_id;
+----------+--------+
| class_id | 数量   |
+----------+--------+
|        1 |      6 |
|        2 |      4 |
+----------+--------+
2 rows in set (0.00 sec)

-- 在select里面有class_id、class_name,group by后面只有id就会出错

mysql> select class_id,class_name,count(*) as '数量' from stu group by class_id;
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'yuge.stu.class_name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

-- 正确的语句,应该是吧select所有列都作为分组条件。
mysql> select class_id,class_name,count(*) as '数量' from stu group by class_id,class_name;
+----------+------------+--------+
| class_id | class_name | 数量   |
+----------+------------+--------+
|        1 | c1         |      6 |
|        2 | c2         |      4 |
+----------+------------+--------+
2 rows in set (0.00 sec)

ncompatible with sql_mode=only_full_group_by

– 正确的语句,应该是吧select所有列都作为分组条件。

mysql> select class_id,class_name,count(*) as '数量' from stu group by class_id,class_name;
+----------+------------+--------+
| class_id | class_name | 数量   |
+----------+------------+--------+
|        1 | c1         |      6 |
|        2 | c2         |      4 |
+----------+------------+--------+
2 rows in set (0.00 sec)

猜你喜欢

转载自blog.csdn.net/weixin_43701183/article/details/114117685