先给出一张表
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;
一般不使用通配符,除非确实需要表中的每个列,否则最好别使用*通配符。
使用通配符可以检索出名字未知的列
select distinct 字段1,字段2... from stu;
# 例: select distinct class_id from stu;
DISTINCT关键字只返回不同的值,若列里有很多个a和很多个b这两种值,只返回a和b
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;
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子句完成后。使用子句的次序不对将产生错误信息。
数据库一般包含大量的数据,很少需要检索表中所有行。
通常只会根据特定操作或报告的所需要提取表数据的子集。
只检索所需数据需要制定搜索条件
select 字段 from tbname where 条件;
同时使用 where 和 order by 时,where 应在前,order by 在后
操作符 | 说明 |
---|---|
= | 等于 |
<> 、!= | 不等于 |
< | 小于 |
<= | 小于或等于 |
> | 大于 |
>= | 大于或等于 |
BETWEEN … and … | 指定两个值之间 |
IS NULL | 空值 |
MySQL允许给出多个WHERE子句。
两种方式:AND和OR连接两个子句。也称逻辑操作符。
AND用在WHERE子句中,用于检索必须符合and连接的所有条件才返回。否则返回 empty set
select 字段 from tbname where 字段=.. and 字段=..;
# 例:
select name from stu where age = 22 and sex = 'm';
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操作符用来指定条件范围,范围中每个条件都能进行匹配。可以与AND和OR连用
select name from stu where class_id in (1,2) and sex='女';
为什么要使用IN操作符?其优点如下:
NOT操作符用来指定除了此条件外的所有数据。
select name from stu where class_id not in (1);
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且总长度为两个字符的数据
select name from stu where name regexp '[0-5]abc'; # 第一个字符为0-5,后面为abc的所有数据
我们经常需要汇总数据而不用把他们实际全部检索出来,为此MySQL提供了专门的函数。
使用这些函数,MySQL查询可用于检索特定数据,分析并形成报表。
比如:
函数 | 说明 |
---|---|
COUNT() | 返回某列的行数 |
MAX() | 返回某列的最大值 |
MIN() | 返回某列的最小值 |
SUM() | 返回某列值的和 |
AVG() | 返回某列的平均值 |
注意:
使用count时,如果指定列名,则指定列的值为空(NULL)的行被忽略,但如果函数中用的星号(*),则不忽略。
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过滤分组
除了能用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)