首頁  >  問答  >  主體

mysql - 一个sql的问题

stat表 字段 uid,act,time
我想取出每个uid最近的一个act
我现在的sql:

select * from (select * from stat order by uid,time desc) a group by uid

这个表数据量比较大,查起来有点慢,有没有更好的办法

甚至这个:

select act,count(*) num from (select * from (select * from stat order by uid,time desc) a group by uid) b group by act

表:

CREATE TABLE `stat` (
  `uid` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
  `act` bigint(20) NOT NULL,
  `time` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`uid`,`act`),
  KEY `index_time` (`time`) USING BTREE,
  KEY `index_act` (`act`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
PHP中文网PHP中文网2743 天前746

全部回覆(4)我來回復

  • 怪我咯

    怪我咯2017-04-17 14:46:08

    先說一下我的看法吧,如果有錯誤的地方,歡迎指正。
    首先,我覺得題主的SQL語句是錯的,看起來結果正確只不過是寄望資料庫在執行group by的實作機制。比如說如果把排序順序改變結果就錯了。
    在使用group by之後,題主能夠查詢的字段要么是在聚集函數裡面,要么就是group by的字段,類似於'select * from a group by uid'這樣的寫法不規範,因為數據庫在按照uid分組之後,會隨機選取一組act和time的欄位值。題主的SQL看起來運作正常應該是在排序之後,資料庫預設選取了排序最前面的。
    我認為對的SQL應該是這樣的:

    select stat.* from stat ,(select uid,max(time) as time from stat group by uid) tmp where stat.uid=tmp.uid  and stat.time=tmp.time;
    

    先分組查詢出每個人執行時間最晚的時間,然後根據uid和time去取得完整的操作資訊。
    如果題主的資料庫對uid加了索引的話,這個 SQL的查詢效率應該還在可以接受的程度。
    一點個人看法。

    我在原來的基礎之上,做了一丟丟修改,在本地測試性能有微小的提升,我本地是三萬組測試數據,題主可以試一試:

    select stat.* from stat ,(select uid,max(time) as time from stat group by uid order by null) tmp where  stat.time=tmp.time and stat.uid=tmp.uid;

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-17 14:46:08

    給查詢條件的那幾個欄位建立索引試試,B數索引呀,B+數索引呀等等

    具體怎麼建立你可以去百度搜一下

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-17 14:46:08

    這個語句為什麼要嵌套子查詢,一條語句不行嗎,不是很清楚邏輯,,,不過正常情況下我都是用explain打印一下查詢信息

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-17 14:46:08

    一條group by就夠了為什麼要寫兩層

    回覆
    0
  • 取消回覆