mysql查詢欄位資料不重複distinct及distinct的多欄位操作
轉載自 【http://www.jb51.net/article/77997.htm】
MySQL通常使用GROUPBY(本質上是排序動作)完成DISTINCT操作,如果DISTINCT操作和ORDERBY操作組合使用,通常會用到臨時表.這樣會影響效能. 在一些情況下,MySQL可以使用索引優化DISTINCT操作,但需要活學活用.本文涉及一個不能利用索引完成DISTINCT操作的例項.
例項1 使用索引優化DISTINCT操作
?1 2 3 4 5 |
create
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;
|
1 |
mysql> explain
select distinct (a)
from m11;
|
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+| 1 | SIMPLE | 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 5 |
create
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;
|
1 |
mysql> explain
select distinct (a)
from m31;
|
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| id | select_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 5 |
create
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;
|
1 |
mysql> 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只能對一個欄位有效,比如:
?1 |
sql= "select DISTINCT title from Table where id>0"
|
當我們需要列出資料中的另一列,比如:
?1 |
sql= "select DISTINCT title,posttime from Table where id>0"
|
得出的結果就不是我們想要的了,所以我們需要用另外的方法來解決這個問題。
下面的是我寫的SQL語句,我不知道是不是很好,但願有更好的人拿出來分享一下:
寫法一:
?1 |
sql = "Select DISTINCT(title),posttime From Table1 Where id>0"
|
寫法二:
?1 |
sql = "Select title,posttime From Table1 Where id>0 group by title,posttime"
|
寫法三:
?1 |
sql= "select title,posttime from Table where id in (select min(id) from Table
|