LENDIEN聯電 冷暖 清淨 除溼 移動式空調 9000BTU任天堂-Switch-NS-公司貨主機-豪華全配組LG樂金 WIFI遠控雙眼小精靈掃地清潔機器人變頻版

2011年4月21日 星期四

mysql取前後各n筆資料

這問題常常會遇到,因為大家都喜歡在網頁上加上「上一筆」、「下一筆」的按鈕
簡單的做法是把連結加個標記,告訴下一個網頁現在是哪一筆,你要抓上一筆還是下一筆,這樣單頁就可以只執行一次query,可是在大家注重SEO的時代,這個做法可以說不太聰明。
於是乎,程式人員只好在一頁裡多下幾次query把上一筆跟下一筆都先抓出來,不過程式人員的特性就是懶!想到要一直下query就不開心,所以呢,網路上就出現了很多類似的討論主題,不過最快速的方式也就是下。兩。次。。。是的,還是不能一次搞定。

簡單的說明下兩次的做法:
假設要找編號228的前後一筆資料,而且編號欄位的值在資料庫裡可能會有跳號狀況,因此絕對不能用+1,-1的做法處理,所以要分別下
SELECT * FROM 資料表 WHERE 編號>=228 ORDER BY 編號 LIMIT 2
SELECT * FROM 資料表 WHERE 編號<228 ORDER BY 編號 DESC LIMIT 1

可是呢,這個是單純的狀況
如果要從a,b兩個資料表抓資料出來編號228前後一筆資料,而且裡面一個類別的欄位值要跟編號228的一樣,但是下sql語法之前還不知道編號228的類別是什麼,如果一樣下
SELECT 編號,a.類別,b.類別名稱 FROM a,b WHERE 編號>=228 AND a.類別=b.類別ORDER BY 編號 LIMIT 2
SELECT 編號,a.類別,b.類別名稱 FROM a,b WHERE 編號<228 AND a.類別=b.類別 ORDER BY 編號 DESC LIMIT 1
就會發現抓出來的資料會擁有不同的類別值……

為了要先得到編號228的類別,就要先下一次
SELECT 編號,類別  FROM a WHERE 編號=228

當然,其實不一定要把這句獨立,可以把他併到上面那個例子裡當一個subquery,就也是2次搞定,不過有可能會得到一句落落長的sql語法,光看就頭昏眼花……
知道228的類別後,再來抓他同類的前後一筆,可是這個時候再下2次就很笨了,因為如果一開始就決定要下3次 ,還上網找答案做什麼呢?
於是我用了UNION
(SELECT '前' as tmp,編號 FROM a WHERE 編號>228 AND 類別=x ORDER BY 編號 LIMIT 1)

UNION
(SELECT '後' as tmp,編號 FROM a WHERE 編號<228 AND 類別=x ORDER BY 編號 DESC LIMIT 1)
tmp欄位只是標一下前後各是哪一筆,萬一228的前後剛好有一邊沒資料,就會比較好判斷

說穿了還是subquery的概念,只是因為前後一筆我們只需要知道部份資料,如果跟228一起搜出來,mysql回傳回來的一大堆資料其實都用不到,這樣就浪費了server資源
而用UNION把兩邊的資料一起抓出來,也會比分2次進資料庫抓資料來的省時間

目前看來好像就只有這幾種方式比較省力了,為什麼他們不出一個nearby的函數,專門用來處理這種狀況呢...............................

沒有留言:

張貼留言