1. 程式人生 > >mysql分析函式的實現(阿里DBA部落格,大開眼界)

mysql分析函式的實現(阿里DBA部落格,大開眼界)

今天收到同事的一需求,要求實現以下功能:

drop table test;

create table test(name varchar(10),name1 varchar(10),count bigint);

delete from test;

insert into test values(’1′,’a',2);

insert into test values(’1′,’b',1);;

insert into test values(’1′,’c',4);

insert into test values(’1′,’d',5);

insert into test values(’1′,’e',7);

insert into test values(’1′,’f',8);

insert into test values(’2′,’g',9);

insert into test values(’2′,’h',0);

insert into test values(’2′,’i',21);

insert into test values(’2′,’j',3);

insert into test values(’2′,’k',4);

insert into test values(’2′,’l',56);

insert into test values(’3′,’m',67);

insert into test values(’3′,’n',89);

insert into test values(’3′,’o',12);

insert into test values(’3′,’p',22);

insert into test values(’3′,’q',23);

insert into test values(’3′,’r',42);

insert into test values(’3′,’s',26);

根據name欄位分組,取出改組內的前4項,並且按照count欄位進行降序排序,由於mysql沒有oracle中的分析函式,看上去很簡單的需求,但是折騰了許久,還是沒有實現,於是乎在網上收羅了一下mysql分析函式是怎麼

實現的 ,找到了mysql分析函式的解決辦法,學習了一下,於是乎把同事的功能實現了;

select name, name1, count  from (select b.name, b.name1, b.count,
if(@name = b.name, @rank := @rank + 1, @rank := 1) as rank,@name:=b.name
from (select name, name1, count    from test order by name asc, count desc) b,
(select @rownum := 0, @name := null, @rank := 0) a) result where rank<5;

結果:

| name | name1 | count |

+——+——-+——-+

| 1    | f     |     8 |

| 1    | e     |     7 |

| 1    | d     |     5 |

| 1    | c     |     4 |

| 2    | l     |    56 |

| 2    | i     |    21 |

| 2    | g     |     9 |

| 2    | k     |     4 |

| 3    | n     |    89 |

| 3    | m     |    67 |

| 3    | r     |    42 |

| 3    | s     |    26 |

+——+——-+——-+

12 rows in set (0.02 sec)

如果上面的sql初次看到有些讓人摸不著頭腦的話,你可以看看他的執行計劃,然後從執行計劃得到一些執行流程,該sql中最核心的技術點為使用自定義變數來儲存sql執行過程中的值:

if(@name = b.name, @rank := @rank + 1, @rank := 1) as rank,@name:=b.name

這條判斷語句對下面結果進行處理,並生成rank,由於下面查詢的結果中對name做了排序,所以@name:=b.name使的相同name值的rank能夠遞增;

+—-+————-+————+——–+—————+——+———+——+——+—————-+

| id | select_type | table      | type   | possible_keys | key  | key_len | ref  | rows | Extra          |

+—-+————-+————+——–+—————+——+———+——+——+—————-+

|  1 | PRIMARY     | <derived2> | ALL    | NULL          | NULL | NULL    | NULL |   19 | Using where    |

|  2 | DERIVED     | <derived4> | system | NULL          | NULL | NULL    | NULL |    1 |                |

|  2 | DERIVED     | <derived3> | ALL    | NULL          | NULL | NULL    | NULL |   19 |                |

|  4 | DERIVED     | NULL       | NULL   | NULL          | NULL | NULL    | NULL | NULL | No tables used |

|  3 | DERIVED     | test       | ALL    | NULL          | NULL | NULL    | NULL |   19 | Using filesort |

如果你對下面的select @rownum := 0, @name := null, @rank := 0看不太明白,可以改寫一下sql:
select name, name1, count from (select b.name, b.name1,b.count,if(@name = b.name, @rank := @rank + 1, @rank := 1) as rank,@name:=b.namefrom (select name, name1, count,@rownum := 0, @name := null, @rank := 0from test order by name asc, count desc) b) result where rank<4;

結果:

+—-+————-+————+——+—————+——+———+——+——+—————-+

| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows | Extra          |

+—-+————-+————+——+—————+——+———+——+——+—————-+

|  1 | PRIMARY     | <derived2> | ALL  | NULL          | NULL | NULL    | NULL |   19 | Using where    |

|  2 | DERIVED     | <derived3> | ALL  | NULL          | NULL | NULL    | NULL |   19 |                |

|  3 | DERIVED     | test       | ALL  | NULL          | NULL | NULL    | NULL |   19 | Using filesort |

+—-+————-+————+——+—————+——+———+——+——+—————-+

轉載自:http://hidba.org/?p=295