1.數據表test的結構和數據如下:
問題:
1.我只想獲取某個項目(project_id=1)的最新評論。(create_time越大,說明評論越新)
按道理可以這樣做:
1)排好序 SELECT * FROM `test` where project_id = 1 order by project_id,create_time desc;
2)然后在上面排好序的基礎上分組
select * from (SELECT * FROM `test` where project_id = 1 order by project_id,create_time desc) t GROUP BY project_id;
結果是看似正確的,實則是錯誤的。
如:修改id為1的create_time,然后再排序:
可以看到id為1的數組被排到最后。再對該結果進行分組:
select * from (SELECT * FROM `test` where project_id = 1 order by project_id,create_time desc) t GROUP BY project_id;
從結果可以看到,我們需要的數據是id為4的數據,但分組后卻拿到了id為1的數據,這顯然是錯誤的。
如果不限定project_id,對整個數據表進行排序:
SELECT * FROM `test` order by project_id,create_time desc;
然后對project_id分組:
select * from (SELECT * FROM `test` order by project_id,create_time desc) t GROUP BY project_id;
從分組后的結果可以看到:對於每一個分組,分組后的結果總是取組中主鍵(id)最小的數據,即group by project_id 總會對project_id執行排序(正序)
而不論臨時表(t)中的project_id是否已排序,然后取組中主鍵id最小(如id為1)的一行數據。換句話說 臨時表t 內的排序 無法影響外層的group by 的操作。
通過上面的實驗可知 select * from (SELECT * FROM `test` order by project_id,create_time desc) t GROUP BY project_id; 無法獲取項目的最新評論
可以通過以下方法獲取項目的最新評論:
(1)
SELECT t.* FROM test t JOIN ( SELECT SUBSTRING_INDEX( group_concat( id ORDER BY create_time DESC ), ',', 1 ) AS id FROM test GROUP BY project_id ) tmp ON t.id = tmp.id;
其結果為:
分析結果可知,此為正確結果。
注:group_concat 用法 (默認連接符為',')
select group_concat(project_id,'-',create_time,'-',status order by create_time desc SEPARATOR ',') as info from test GROUP BY project_id;
SUBSTRING_INDEX 用法:下面的例子取排序好的分組的第一條數據