作者回复: select count(*),floor(rand(0)*2)x from users group by x; 先该语句会产生一张虚拟表count(*)-x,该虚拟表的主键是group by后指定的x,在初始时该虚拟表为空;在执行group by的过程中,一条一条的遍历user表,获得x字段的值,该x字段的值是通过floor(rand(0)*2)计算得来;得到了x的值后,根据x的值将其插入count(*)-x表中,如果x字段的值在虚拟表count(*)-x中已经存在,就将count(*)的值增加1,如果x字段的值在虚拟表count(*)-x在虚拟表中不存在,就会将新的记录插入到该虚拟表中,在插入过程中又会执行一次floor(rand(0)*2)的计算,因为floor(rand(0)*2)是随机生成0、1数字,这也就有一定的几率导致在插入过程中生成的x的值与遍历原表过程中得到的x的值不一致,而因为只有0和1两种情况,一旦在插入过程中生成的x的值与遍历原表过程中得到的x值不一致,就会与虚拟表中已有记录的x值重复。又因为x是该虚拟表的主键,在该虚拟表中是不可以重复的,也就出现上面的报错 总的来说floor(rand(0)*2)在该语句中会执行两次,一次是在遍历原表中的数据的时候,会计算一次x的值;一次是当虚拟表中没有该x的值,准备将新的记录插入虚拟表中的时候。一旦这两次的计算结果不一致,就会导致插入过程的报错。
作者回复: 主流的报错方式就是前三种,如果同学有兴趣可以自行研究哦~
作者回复: 不是不会生成,而是不会报错,要理解其中每个语句的原理哦