MySQL SELECT 语句
查询结果的顺序和 select 子句中的顺序一致
order by
排序
按照字段进行排序
order by 字段 升序|降序 (asc|desc)
默认升序
允许多字段排序, 指的是先按照第一个字段排序, 如果说,不能区分, 使用下一个字段排序.
select * from php_one order by span desc, begin_date asc;
注意, 如果是分组, 则应该使用对分组字段进行排序的
group by 语法.
limit
限制获取数据的数值
limit 语法: limit offset, row_count
索引位置从默认0开始, 如果获取数量大于所有余下记录数, 则获取所有余下记录.
select * from php_one order by span desc, begin_date asc limit 2;
distinct
去掉重复记录
重复的记录指的是字段值都相同的记录, 而不是部分字段相同的记录.(判断重复, 比较两条记录 distinct 后面的每一个字段, 如果都相同则为重复)
相对的是all, 表示所有, 默认就是 all 行为.
select distinct days from teacher_class;
union
联合查询
将多条select语句的结果合并到一起, 称为联合操作
(select子句1) union (select子句2);
子语句的括号是可选的, 不过加上括号逻辑更加清楚
应用场景:
获取数据的条件出现逻辑冲突, 或者很难在一个逻辑内表示, 就可以拆分成多个逻辑, 分别实现, 最后将结果合并到一起
union 如果union存在重复的记录, 那么会合并重复项, 可以通过 union 选项 all 设置不合并重复项
排序:
子语句结果排序:
将子语句 order by 包裹在括号内
子语句的 order by, 只有在 order by 配合 limit 时, 排序才生效(在union联合之后).
对所有结果统一排序:
只需要在最后一个语句后增加排序,
规定多个select语句的检索到的字段个数必须相同,
数据类型上也应该一致(类型可以转换成功也可以)
检索结果的列名由第一条select子语句的列名而定
MySQL 子查询
为了降低业务逻辑的复杂度
思想: 将 SELECT 查询结果当做一个值来看待, 分步骤解决复杂问题.
场景:
查询代课最多天数的老师信息
思路:
先获取最多的代课天数是多少天, 在判断选哪个老师的代课天数, 和最大值是一样的.
MySQL允许将查询结果作为一个值来使用;
SELECT t_name gender from teacher_class where span = (SELECT max(span) from teacher_class);
如果一个查询语句出现在另一个语句内部, 则该语句就是子查询语句; 该子查询必须用括号括起来;
子查询分类:
不同的分类会有不同的使用方式
分类标准:
子查询出现的位置;
子查询的返回值形式;
返回值分类:
单一值(标量子查询)
列子查询
行子查询
表(多行多列)
出现位置:
where(subquery)
from(subquery)
exist(subquery)
如何使用
标量子查询
获取一个值之后, 使用关系运算符进行判断
=, , >=, <=, !=
列子查询: 获取一列
使用成员操作符: in|not in
in 等同于 =any()
all(集合) 集合中的每一个元素
!=all(集合) 等同于 not int
!=any(集合) 只要和集合中一个元素不同即成立
场景:
获取带个 A 班的老师们还带过那些班.
select t_name, c_name from teacher_class where t_name in (select t_name from teacher_class where c_name='php0228');
行子查询
返回一行
select distinct gender, c_name from teacher_class where t_name = "李白";
select t_name gender , c_name from teacher_class where (gender, c_name) = (select distinct gender, c_name from teacher_class where t_name = "李白" limit 1);
表子查询
返回一个表
from语句要求后面跟一个表, 而不是一个结果. 所以应该给这个查询结果起一个别名
外部查询所使用的的列名, 是由子查询决定
select * from tbl_name where condition;
select teacher from (select t_name as teacher, c_name, span from teacher_class where days > 10) as temp where t_name like '李%';
exists子查询
exists(subquery) 出现在where中, 有时也分类为where子查询
判断依据: 如果子查询可以返回数据, 则认为exists表达式返回真, 否则返回假
类似双重循环
select * from teacher_class where exists (select * from teacher where teacher_class.id=t_id);
/*等同于下面*/
select * from teacher_class where
id in (select t_id from teacher);
/*上面 id 是teacher_class 的字段 */
解析:
exists: 先获得每一条teacher_class的数据, 获得id字段, 然后去teacher表内查找对应值
in: 先获得所有t_id的可能性, 再去检索teacher_class数据时, 判断当前的id是否在t_id集合内;
MySQL 连接(join)查询
内连接
外连接
自然连接
每个实体, 一个表
一个业务逻辑, 使用多个实体的信息, 多张表应该放在一起使用, 将多个表的记录连接起来
总体思路:
先将所有数据按照某种条件, 连接起来, 再进行筛选处理
内连接
tbl_left inner join tbl_left on 连接条件
数据内部的连接, 要求多个数据都必须存在才能进行连接
只显示有连接的数据
内连接, 在连接时, 可以省略连接条件. 意味着, 所有的左表记录(M条)都要与右表的记录(N条)做一个连接, 共存在M*N个连接.
没有条件的内连接称为交叉连接, 或者笛卡尔积, MySQL中可以使用 cross join 代替 inner join
MySQL inner join 是默认的连接方式, 所以可以省略 inner
有条件的内连接
会在连接时. 过滤非法的连接.
where写法
on写法
using写法
where 过滤操作, 先形成笛卡尔积, 再过滤 where id=t_id
on 连接操作, 连接时进行条件判断 on id=t_id
using 要求进行连接的两个表的进行连接判断的条件的字段相同(写法一样) using(id)
建议: 再有同名字段时, 使用using, 而在通用条件使用on
在数据过滤时(不是连接过滤)使用where
外连接
并非所有数据都可以进行连接, 即存在没有连接的数据, 显示没有连接的数据
查询条件和内连接通用, 不过外连接不能使用 where 作为连接条件
表别名, 保证简洁和清晰
列别名, 简洁, 防止冲突
左外连接
右外连接
全外连接(MySQL不支持)
左外连接
连接时, 如果出现左边表的数据连接不到右表情况, 最终结果左表数据保留; 出现右表数据不能连接左表, 右表数据丢掉
using用法: 去掉结果中的重复字段, 并放在列前;
外连接必须有条件, 不能写没有条件的内连接
右外连接
与左外连接相似
全外连接
MySQL不支持全外连接,可以通过下面方式模拟
左外连接 union 右外连接;
自然连接
通过MySQL自己的判断完成连接的过程, 不需要指定连接条件
natural join
自然连接分为内外之分
内: natural join
外: 左外(natural left join), 右外(natural right join)
使用
连接时支持多表连接
info_class; id class_name
info_student; id, student_name class_id;
info_student_info, id student_detail
select s.* si.* from info_class as c left join info_student as s on c.id=s.class_id left join info_student_info as si on s.id=si.id where c.class_name = 'php0331'