問題是:
數據庫有一個表 code,里面有個點擊量字段click_num和一個類別字段kind以及其它信息字段,
現在要搜出每個類別中點擊量最大的那條記錄,如果是10個類別,那么結果應該是10條記錄,
如果最大點擊量有兩個相同的只要一條。
經過N次搜索,N次檢測網上的解決SQL語句,終於找到個優雅的而且結果正確的SQL,這個是一個博客作者在Mysql的官方文檔里面發現的。
禁不住收藏了,以備后用。
- select id,kind,click_num from code as a
- where click_num=(select max(b.click_num)
- from code as b
- where a.kind = b.kind
- );
特別注意:
這個語句在SQLite上測試正常,速度很快。但是在我機器上的MySql5.0上執行后就死機了,其他版本的Mysql不知道什么情況。
上面的語句還不能滿足我的第二個要求就是:如果某類別中最大點擊量有兩個相同的記錄,只要一條。
下面是我附加的解決辦法:
篩選,保證每個類別只有一條,(kind,id改為所有列,結果就是對應的記錄了)
- select *
- from (select id,kind,click_num from code as a
- where click_num=(select max(b.click_num)
- from code as b
- where a.kind = b.kind
- )
- ) as a
- group by kind
后續:
結合以往的Mysql使用經驗發現Mysql的一個最大問題就是在一個查詢的where子句中如果包含對前面select的表的查詢那么CPU占用就會飆升Mysql服務停止。可以說是自連接查詢問題,不知道這是不是個bug,5.0,5.1版本都有這個問題,回頭看看上面的SQL語句正好符合了這個問題,解決辦法就是把子查詢的表弄成一個臨時表或者視圖總之不能和前面的select的表是同一個表,那么問題就解決了,於是乎,對上面的SQL稍作修改就可以在Mysql上跑了。
修改過程:
1.建立一個視圖max_click,存儲的是每個類別最大的點擊量
- create view max_click as select max(click_num) as click_num,kind
- from code
- group by kind;
2.篩選,保證每個類別只有一條記錄
- select *
- from (select id,kind,click_num
- from code
- where click_num = ( select b.click_num
- from max_click as b
- where code.kind = b.kind
- )
- ) as a
- group by kind;
運行正常,速度0.78秒。(表中一共23000條數據) Okay! 大功告成!
最前面第一個SQL在MSSQL上運行不知道行不行,我想在SQLite能正常在MSSQL上應該沒問題,看來Mysql需要改進的地方很多啊,同樣是開源的SQLite就可以做到的,而且SQLite那么輕量級就幾百KB,Mysql更應該能做到。
