MySQL知识树 集合操作
我们之前讲到了联接操作【对于联接操作的学习烦请移步:http://www.cnblogs.com/seker/p/6523592.html】,联接操作可以看做是表之间的水平操作,通过联接操作得到的记录包含两表的列。
集合操作可以看做是表之间的垂直操作,通过集合操作得到的记录中的列名仅由第一个select决定。
MySQL支持两种集合操作;union all和union distinct,union distinct可以简写为union。进行集合操作的两表必须拥有两同的列数(列名不同没有影响),例如表A有5列,那表B也必须有5列,列数不同是不允许进行集合操作的。另外若列的数据类型不一样,没有关系,MySQL会隐式帮我们做类型转换。
“进行集合操作的两表必须拥有两同的列数”,来看一个实例,select * from t_commodity c union select * from t_commodity_type ct;(这里我们为了方便演示使用了*,在实际开发中不建议这样做)
MySQL会提示如下错误,这是因为两表的列数不同。
在进行集合操作时,建议最好给参与集合操作的各select添加括号,不然可能会遭遇一些问题,例如在select中使用了order by和limit,来看一个实例,select * from t_user_collect uc order by uc.id_temp desc limit 1,3 union select * from t_user_order uo order by uo.id desc limit 1,3;(这里我们为了方便演示使用了*,在实际开发中不建议这样做)
如下是MySQL给出的提示,意思是“union和order by的使用不正确”。
现在我们给各个select加上括号,(select * from t_user_collect uc order by uc.id_temp desc limit 1,3) union (select * from t_user_order uo order by uo.id desc limit 1,3);(这里我们为了方便演示使用了*,在实际开发中不建议这样做)
我们可以看到能够正常得到数据,
这里需要进行一下补充说明,select * from t_user_collect uc order by uc.id_temp desc limit 1,3; 单独执行有3条数据,
select * from t_user_order uo order by uo.id desc limit 1,3; 单独执行也有3条数据,
为什么实际查询出来的仅有5条数据呢?因为前面我们有说到union是union distinct的简写,因此其中一条重复的数据被distinct给过滤掉了。
另外我们从得到的列名可以看出其都来自第一个select的表t_user_collect,这也就解释了我们前面说到的“通过集合操作得到的记录中的列名仅由第一个select决定”。
union all和union distinct
我们来说一下union distinct的实现方式:
①创建一张临时表,这张临时表就是一张虚拟表;
②为这张临时表的列添加唯一索引;
③将进行集合操作的数据插入到临时表;
④返回临时表;
从上述过程中我们可以看到,在创建了临时表后就为其添加了唯一索引,因此在将数据插入到临时表中时,若插入的数据会导致唯一索引重复,则这一条数据是不允许被插入到临时表中的,这也就完成了去重操作。
当然由于向临时表中添加了唯一索引,因此会影响向临时表中插入数据的速度,所以如果你确定进行集合操作的两个表中没有重复数据,则建议使用union all,它会得到两表中所有的数据,不会有去重这一行为。