共事提了个需要,如下测试表,有code、cdate和ctotal三列,
select * from tt;

当初要失去code的惟一值,但同时带着cdate和ctotal两个字段。

提起"惟一值",想到的就是distinct。distinct关键字能够过滤多余的重复记录只保留一条。

distinct反对单列去重和多列去重,如果是单列去重,扼要易懂,即雷同值只保留1个,如下所示,
select distinct code from tt;

多列去重则是依据指定的去重列信息进行,即只有所有指定的列信息都雷同,才会被认为是反复的信息,如下所示,code、cdate和ctotal都雷同,才会返回记录,因而不是字面上的了解,即只有code是distinct的,cdate和ctotal无需关注。实际上当distinct利用到多个字段的时候,其利用的范畴是其前面的所有字段,而不只是紧贴着它的一个字段,即distinct同时作用了三个字段,code、cdate和ctotal,并不只是code字段,select distinct code, cdate, ctotal from tt;

而且distinct只能放到所有字段的后面,如果像这种,distinct之前有其它字段,则会提醒谬误,

select cdate, ctotal, distinct code from tt;SQL 谬误 [1064] [42000]: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'distinct code from tt' at line 1

然而如上SQL应用distinct关键字,并没有满足需要,即失去code的惟一值,但同时带着cdate和ctotal两个字段,能够看到有很多雷同的code。

除了distinct,group by子句也能够去重,从需要的了解上,如果依照code做group by,应该就能够失去惟一的code了,然而理论执行,提醒这个谬误,

select code, cdate, ctotal from tt group by code;SQL 谬误 [1055] [42000]: Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.tt.code' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

很常见的谬误,因为sql_mode中含only_full_group_by规定,

show variables like '%sql_mode%';ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

only_full_group_by规定是指对group by进行查问的SQL,不容许select局部呈现group by中未呈现的字段,也就是select查问的字段必须是group by中呈现的或者应用聚合函数的,即校验更加严格。

P.S. MySQL不同版本sql_mode默认值可能是不同的,因而在数据库降级配合的利用迁徙过程中,尤其要留神像only_full_group_by这种校验规定的扭转,很可能是个坑。

仅针对以后这个问题,能够在会话级,批改sql_mode,调整校验的强度,删除only_full_group_by,

set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

此时,应用group by,

select code, cdate, ctotal from tt group by code;

就能够失去想要的成果了,

除了group by,还能够应用group_concat函数,配合distinct,达到雷同成果。

咱们合成来做,能够看到group_concat(code),失去的是所有记录的code值拼接成新字段,

select group_concat(code), cdate, ctotal from tt group by code;


group_concat中加上distinct,就能够过滤所有的反复值,满足了需要,

select group_concat(distinct code), cdate, ctotal from tt group by code;


当然,这种在会话级通过改变sql_mode实现的门路,还须要思考场景,因为短少only_full_group_by的校验,依照code聚类了,但cdate和ctotal的值很可能是不惟一的,返回的后果,只能精确形容code的数据状况,不能代表cdate和ctotal的实在数据状况。因而,任何计划的抉择,都须要结合实际的场景需要,咱们找的计划,不肯定是最好的,但须要最合适的。本文关键字:#SQL# #去重#