关于mysql:MySQL多列字段去重的案例实践

0次阅读

共计 2232 个字符,预计需要花费 6 分钟才能阅读完成。

共事提了个需要,如下测试表,有 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# #去重 #

正文完
 0