mysql查询字段数据不重复distinct及distinct的多字段操作
MySQL通常使⽤GROUPBY(本质上是排序动作)完成DISTINCT操作,如果DISTINCT操作和ORDERBY操作组合使⽤,通常会⽤到临时表.这样会影响性能. 在⼀些情况下,MySQL可以使⽤索引优化DISTINCT操作,但需要活学活⽤.本⽂涉及⼀个不能利⽤索引完成DISTINCT操作的实例.
实例1 使⽤索引优化DISTINCT操作
1 2 3 4 5create table m11 (a int, b int, c int, d int, primary key(a)) engine=INNODB;
insert into m11 values(1,1,1,1),(2,2,2,2),(3,3,3,3),(4,4,4,4),(5,5,5,5),(6,6,6,6),(7,7,7,7),(8,8,8,8); explain select distinct(a) from m11;
1mysql> explain select distinct(a) from m11;
代码如下:
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+| 1 | SI
MPLE | m11 | NULL | index | PRIMARY | PRIMARY | 4 | NULL | 1 | 100.00 | Using index |+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
说明:
1 'a'列上存在主键索引,MySQL可以利⽤索引(key列值表明使⽤了主键索引)完成了DISTINCT操作.
2 这是使⽤索引优化DISTINCT操作的典型实例.
实例2 使⽤索引不能优化DISTINCT操作
1 2 3 4 5create table m31 (a int, b int, c int, d int, primary key(a)) engine=MEMORY;
insert into m31 values(1,1,1,1),(2,2,2,2),(3,3,3,3),(4,4,4,4),(5,5,5,5),(6,6,6,6),(7,7,7,7),(8,8,8,8); explain select distinct(a) from m31;
1mysql> explain select distinct(a) from m31;
代码如下:
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| id | sel
ect_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| 1 | SIMPLE | m31 | NULL | ALL | NULL | NULL | NULL | NULL | 8 | 100.00 | NULL |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
说明:
1 从查询执⾏计划看,索引没有被使⽤.
2 对⽐实例1的建表语句,只是存储引擎不同.
3 为什么主键索引没有起作⽤? 难道MEMORY存储引擎上的索引不可使⽤?
实例3 使⽤索引可以优化DISTINCT操作的Memory表
1 2 3 4 5create table m33 (a int, b int, c int, d int, INDEX USING BTREE (a)) engine=MEMORY; insert into m33 values(1,1,1,1),(2,2,2,2),(3,3,3,3),(4,4,4,4),(5,5,5,5),(6,6,6,6),(7,7,7,7),(8,8,8,8); explain select distinct(a) from m33;
1mysql> explain select distinct(a) from m33;
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------+| 1 | SIMPLE | m33 | NULL | index | NULL | a | 5 | NULL | 8 | 100.00 | NULL |+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------+
说明:
1 'a'列上存在主键索引,MySQL可以利⽤索引(key列值表明使⽤了主键索引)完成了DISTINCT操作.
2 对⽐实例2,可以发现,⼆者都使⽤了Memory引擎. 但实例3指名使⽤Btree类型的索引.
3 实例2没有指定使⽤什么类型的索引,MySQL将采⽤默认值. MySQL⼿册上说:
As indicated by the engine name, MEMORY tables are stored in memory. They use hash indexes by default, which makes them very fast for single-value lookups, and very useful for creating temporary tables.
结论:
1 看索引对查询的影响,要注意索引的类型.
2 HASH索引适合等值查,但不适合需要有序的场景,⽽Btree却适合有序的场景.
3 看查询执⾏计划,发现索引没有被使⽤,需要进⼀步考察索引的类型.
DISTINCT不能选择多个字段的解决⽅法
在实际应⽤中,我们经常要选择数据库某表中重复数据,通常我们是使⽤DISTINCT函数。
但DISTINCT只能对⼀个字段有效,⽐如:
1sql="select DISTINCT title from Table where id>0"
当我们需要列出数据中的另⼀列,⽐如:
1sql="select DISTINCT title,posttime from Table where id>0"
得出的结果就不是我们想要的了,所以我们需要⽤另外的⽅法来解决这个问题。
下⾯的是我写的SQL语句,我不知道是不是很好,但愿有更好的⼈拿出来分享⼀下:
写法⼀:
distinct查询
1sql = "Select DISTINCT(title),posttime From Table1 Where id>0"
写法⼆:
1sql = "Select title,posttime From Table1 Where id>0 group by title,posttime"写法三:
1sql="select title,posttime from Table where id in (select min(id) from Table

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。