mysql中过滤重复记录之distinct用法
本文章主要是讲述了关于利用mysql中distinct来过滤一些重启的记录,有需要的朋友可参考一下。
下面我们就通过几个简单的 Query 示例来展示一下 DISTINCT 的实现。
1.首先看看通过松散索引扫描完成 DISTINCT 的操作:
代码如下 | 复制代码 |
sky@localhost : example 11:03:41> EXPLAIN SELECT DISTINCT group_id -> FROM group_messageG *************************** 1. row *************************** id: 1 SELECT_type: SIMPLE table: group_message type: range possible_keys: NULL key: idx_gid_uid_gc key_len: 4 ref: NULL rows: 10 Extra: Using index for group-by 1 row in set (0.00 sec) |
我们可以很清晰的看到,执行计划中的 Extra 信息为“Using index for group-by”,这代表什么意思?为什么我没有进行 GROUP BY 操作的时候,执行计划中会告诉我这里通过索引进行了 GROUP BY 呢?其实这就是于 DISTINCT 的实现原理相关的,在实现 DISTINCT的过程中,同样也是需要分组的,然后再从每组数据中取出一条返回给客户端。而这里的 Extra 信息就告诉我们,MySQL 利用松散索引扫描就完成了整个操作。当然,如果 MySQL Query Optimizer 要是能够做的再人性化一点将这里的信息换成“Using index for distinct”那就更好更容易让人理解了,呵呵。
2.我们再来看看通过紧凑索引扫描的示例:
代码如下 | 复制代码 |
sky@localhost : example 11:03:53> EXPLAIN SELECT DISTINCT user_id -> FROM group_message -> WHERE group_id = 2G *************************** 1. row *************************** id: 1 SELECT_type: SIMPLE table: group_message type: ref possible_keys: idx_gid_uid_gc key: idx_gid_uid_gc key_len: 4 ref: const rows: 4 Extra: Using WHERE; Using index 1 row in set (0.00 sec) |
这里的显示和通过紧凑索引扫描实现 GROUP BY 也完全一样。实际上,这个 Query 的实现过程中,MySQL 会让存储引擎扫描 group_id = 2 的所有索引键,得出所有的 user_id,然后利用索引的已排序特性,每更换一个 user_id 的索引键值的时候保留一条信息,即可在扫描完所有 gruop_id = 2 的索引键的时候完成整个 DISTINCT 操作。
3.下面我们在看看无法单独使用索引即可完成 DISTINCT 的时候会是怎样:
代码如下 | 复制代码 |
sky@localhost : example 11:04:40> EXPLAIN SELECT DISTINCT user_id -> FROM group_message -> WHERE group_id > 1 AND group_id *************************** 1. row *************************** id: 1 SELECT_type: SIMPLE table: group_message type: range possible_keys: idx_gid_uid_gc key: idx_gid_uid_gc key_len: 4 ref: NULL rows: 32 Extra: Using WHERE; Using index; Using temporary 1 row in set (0.00 sec) |
当 MySQL 无法仅仅依赖索引即可完成 DISTINCT 操作的时候,就不得不使用临时表来进行相应的操作了。但是我们可以看到,在 MySQL 利用临时表来完成 DISTINCT 的时候,和处理 GROUP BY 有一点区别,就是少了 filesort。实际上,在 MySQL 的分组算法中,并不一定非要排序才能完成分组操作的,这一点在上面的 GROUP BY 优化小技巧中我已经提到过了。实际上这里 MySQL 正是在没有排序的情况下实现分组最后完成 DISTINCT 操作的,所以少了 filesort 这个排序操作。
4.最后再和 GROUP BY 结合试试看:
代码如下 | 复制代码 |
sky@localhost : example 11:05:06> EXPLAIN SELECT DISTINCT max(user_id) -> FROM group_message -> WHERE group_id > 1 AND group_id -> GROUP BY group_idG *************************** 1. row *************************** id: 1 SELECT_type: SIMPLE table: group_message type: range possible_keys: idx_gid_uid_gc key: idx_gid_uid_gc key_len: 4 ref: NULL rows: 32 Extra: Using WHERE; Using index; Using temporary; Using filesort 1 row in set (0.00 sec) |
最后我们再看一下这个和 GROUP BY 一起使用带有聚合函数的示例,和上面第三个示例相比,可以看到已经多了 filesort 排序操作了,正是因为我们使用了 MAX 函数的缘故。要取得分组后的 MAX 值,又无法使用索引完成操作,只能通过排序才行了。
在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的所有值。其原因是distinct只能返回它的目标字段,而无法返回其它字段,这个问题让我困扰了很久
下面先来看看例子:
代码如下 | 复制代码 |
|
库结构大概这样,这只是一个简单的例子,实际情况会复杂得多
比如我想用一条语句查询得到name不重复的所有数据,那就必须使用distinct去掉多余的重复记录
代码如下 | 复制代码 |
select distinct name from table |
得到的结果是:
代码如下 | 复制代码 |
name a b c |
好像达到效果了,可是,我想要得到的是id值呢?改一下查询语句吧:
代码如下 | 复制代码 |
select distinct name, id from table |
结果会是:
代码如下 | 复制代码 |
|
distinct怎么没起作用?作用是起了的,不过他同时作用了两个字段,也就是必须得id与name都相同的才会被排除,我们再改改查询语句:
代码如下 | 复制代码 |
select id, distinct name from table |
很遗憾,除了错误信息你什么也得不到,distinct必须放在开头,难到不能把distinct放到where条件里?能,照样报错。。。。。。。
试了半天,也不行,最后在mysql手册里找到一个用法,用group_concat(distinct name)配合group by name实现了我所需要的功能,兴奋,天佑我也,赶快试试
报错。。。。。。。。。。。。郁闷。。。。。。。连mysql手册也跟我过不去,先给了我希望,然后又把我推向失望,好狠那。。。。
再仔细一查,group_concat函数是4.1支持,晕,我4.0的。没办法,升级,升完级一试,成功。。。。。。
终于搞定了,不过这样一来,又必须要求客户也升级了
突然灵机一闪,既然可以使用group_concat函数,那其它函数能行吗?
赶紧用count函数一试,成功,我。。。。。。。想哭啊,费了这么多工夫。。。。。。。。原来就这么简单。。。。。。
现在将完整语句放出:
代码如下 | 复制代码 |
select id,name, count(distinct name) from table group by name |
结果:
代码如下 | 复制代码 |
|
最后一项是多余的,不用管就行了,目的达到。。。。。
哦,对,再顺便说一句,group by 必须放在 order by 和 limit之前,不然会报错,差不多了,我继续忙碌。。。。。。
原文
这篇文章是我从别人那里转来的,在自己的项目中也遇到了这样的问题,我的sql语句是向下面这样写的:
代码如下 | 复制代码 |
SELECT attention_join.memberID,nickName,headpic,attention_join.time FROM attention_join JOIN member ON attention_join.memberID = member.memberID JOIN member_meta ON member.memberID = member_meta.memberID GROUP BY attention_join.memberID ORDER BY attention_join.time DESC |
意思是 '按 加入/关注 小组的时间降序,查出小组内的会员' ,但是语句里并没有用到向上文说的count()关键字,这个也让我很不解,mysql没有详细的学习过,它的 group by 关键字的用法好像和 sqlserver 的有很大不同,这个等有时间了,在查查看吧,现在没有时间了
哦,对了,我的mysql版本是:
服务器版本: 5.1.54-1 ubuntu4
协议版本: 10

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Laravel 是一款 PHP 框架,用于轻松构建 Web 应用程序。它提供一系列强大的功能,包括:安装: 使用 Composer 全局安装 Laravel CLI,并在项目目录中创建应用程序。路由: 在 routes/web.php 中定义 URL 和处理函数之间的关系。视图: 在 resources/views 中创建视图以呈现应用程序的界面。数据库集成: 提供与 MySQL 等数据库的开箱即用集成,并使用迁移来创建和修改表。模型和控制器: 模型表示数据库实体,控制器处理 HTTP 请求。

MySQL和phpMyAdmin是强大的数据库管理工具。1)MySQL用于创建数据库和表、执行DML和SQL查询。2)phpMyAdmin提供直观界面进行数据库管理、表结构管理、数据操作和用户权限管理。

MySQL与其他编程语言相比,主要用于存储和管理数据,而其他语言如Python、Java、C 则用于逻辑处理和应用开发。 MySQL以其高性能、可扩展性和跨平台支持着称,适合数据管理需求,而其他语言在各自领域如数据分析、企业应用和系统编程中各有优势。

文章摘要:本文提供了详细分步说明,指导读者如何轻松安装 Laravel 框架。Laravel 是一个功能强大的 PHP 框架,它 упростил 和加快了 web 应用程序的开发过程。本教程涵盖了从系统要求到配置数据库和设置路由等各个方面的安装过程。通过遵循这些步骤,读者可以快速高效地为他们的 Laravel 项目打下坚实的基础。

在MySQL中,外键的作用是建立表与表之间的关系,确保数据的一致性和完整性。外键通过引用完整性检查和级联操作维护数据的有效性,使用时需注意性能优化和避免常见错误。

MySQL和MariaDB的主要区别在于性能、功能和许可证:1.MySQL由Oracle开发,MariaDB是其分支。2.MariaDB在高负载环境中性能可能更好。3.MariaDB提供了更多的存储引擎和功能。4.MySQL采用双重许可证,MariaDB完全开源。选择时应考虑现有基础设施、性能需求、功能需求和许可证成本。

SQL是一种用于管理关系数据库的标准语言,而MySQL是一个使用SQL的数据库管理系统。SQL定义了与数据库交互的方式,包括CRUD操作,而MySQL实现了SQL标准并提供了额外的功能,如存储过程和触发器。

MySQL和phpMyAdmin可以通过以下步骤进行有效管理:1.创建和删除数据库:在phpMyAdmin中点击几下即可完成。2.管理表:可以创建表、修改结构、添加索引。3.数据操作:支持插入、更新、删除数据和执行SQL查询。4.导入导出数据:支持SQL、CSV、XML等格式。5.优化和监控:使用OPTIMIZETABLE命令优化表,并利用查询分析器和监控工具解决性能问题。
