这里有新鲜出炉的 Mysql 教程, 程序狗速度看过来!
Mysql 关系型数据库管理系统
MySQL 是一个开放源码的小型关联式数据库管理系统, 开发者为瑞典 MySQL AB 公司 MySQL 被广泛地应用在 Internet 上的中小型网站中由于其体积小速度快总体拥有成本低, 尤其是开放源码这一特点, 许多中小型网站为了降低网站总体拥有成本而选择了 MySQL 作为网站数据库
在使用 mysql 时, 有时需要查询出某个字段不重复的记录, 虽然 mysql 提供 有 distinct 这个关键字来过滤掉多余的重复记录只保留一条, 但往往只用它来返回不重复记录的条数, 而不是用它来返回不重记录的所有值
前几天在做一个需求的时候, 需要清理 mysql 中重复的记录, 当时的想法是通过代码遍历写出来, 然后觉得太复杂, 心里想着应该可以通过一个 sql 语句来解决问题的查了资料, 请教了大佬之后得出了一个很便利的 sql 语句, 这里分享下这段 sql 语句和思路
需求分析
数据库中存在重复记录, 删除保留其中一条 (是否重复判断基准为多个字段)
解决方案
碰到这个需求的时候, 心里大概是有思路的最快想到的是可以通过一条 sql 语句来解决, 无奈自己对于复杂 sql 语句的道行太浅, 所以想找大佬帮忙
找人帮忙
因为这个需求有点着急, 所以最开始想到的是, 可以找这方面的同行来解决, 然后分享这个问题给同事, 结果这货随便百度了一下, 就甩给我一个从未用过的 sql 语句, 让我自己尝试, 心里万匹那啥啥啥奔腾而过...
自己百度
找到了一条 sql 语句:
- DELETE
- FROM
- vitae a
- WHERE
- (a.peopleId, a.seq) IN (
- SELECT
- peopleId,
- seq
- FROM
- vitae
- GROUP BY
- peopleId,
- seq
- HAVING
- count(*) > 1
- )
- AND rowid NOT IN (
- SELECT
- min(rowid)
- FROM
- vitae
- GROUP BY
- peopleId,
- seq
- HAVING
- count(*) > 1
- )
这条语句是在 MySQL 中删除重复数据只保留一条 这篇文章里找到的这条 sql 思路很明显, 有以下 3 步:
SELECT peopleId, seq FROM vitae GROUP BY peopleId, seq HAVING count(*) > 1
查询出表中重复记录作为条件
SELECT min(rowid) FROM vitae GROUP BY peopleId, seq HAVING count(*) > 1
查询出表中重复记录中 ID 最小的值为第二个条件
最后根据以上两个条件, 删除 除 重复记录中最小 ID 的其余重复记录
但是很无奈的是, 运行这条语句出现了错误, 大致报错意思是, 不能在查询的时候同时更新这个表
代码解决
根据上面这个 sql 语句想到或许可以通过代码的方式, 两步来达到同样的目的:
先取出重复的数据集
根据查询到的数据集, 循环删除其余的重复数据
想法是有了, 写出来也很快, 但是一运行吓我一跳, 竟然需要 116s 左右, 然后自己就想一定要找到可以使用的 sql 语句, 贴一下代码和运行结果:
完美的去重留一 SQL
最后在一个技术群里得到了完美的答案, 看这条 sql 语句:
- DELETE consum_record
- FROM
- consum_record,
- (
- SELECT
- min(id) id,
- user_id,
- monetary,
- consume_time
- FROM
- consum_record
- GROUP BY
- user_id,
- monetary,
- consume_time
- HAVING
- count(*) > 1
- ) t2
- WHERE
- consum_record.user_id = t2.user_id
- and consum_record.monetary = t2.monetary
- and consum_record.consume_time = t2.consume_time
- AND consum_record.id > t2.id;
上面这条 sql 语句, 仔细看一下, 揣摩出思路也不难, 大概也分为 3 步来理解:
(SELECT min(id) id, user_id, monetary, consume_time FROM consum_record GROUP BY user_id, monetary, consume_time HAVING count(*) > 1 ) t2
查询出重复记录形成一个集合 (临时表 t2), 集合里是每种重复记录的最小 ID
consum_record.user_id = t2.user_id and consum_record.monetary = t2.monetary and consum_record.consume_time = t2.consume_time
关联 判断重复基准的字段
根据条件, 删除原表中 id 大于 t2 中 id 的记录
看到这个语句的时候, 心里想这也太厉害了这么一个简单的 sql 语句, 竟然可以解决这么复杂的问题, 涨姿势了~
运行起来也超级快, 原先的代码循环执行, 需要 116s 左右, 而这里 0.3s 就可以了, 厉害了~
总结
作为一个 php 程序猿, 按理来说 sql 这里是不能拖后腿的, 无奈实际中, 需要忙碌的事情太多, 现在的 sql 水平也只是处于在一个普通的层次中, 以后找机会一定要补一下这方面的知识
今天就分享到这里啦
来源: http://www.phperz.com/article/18/0227/361385.html