前言
很多情況下都有有列表頁面展示,如購物網站,導航頁,甚至搜索引擎都會有列表頁。一旦涉及到列表頁就會有排序問題,有排序頁面,就有人為干預排序,這樣才能賺錢嘛
場景描述
現有產品列表,源自表product,字段有product_id,name,現在product_id為2,6,8的產品的店主花了點錢,想把產品推到列表的前面,那么現在該如何處理?
方案1
我在項目中這么干過
select product_id,name from product order by product_id not in (2,6,8) asc limit 10
這樣可以滿足要求
這里的“not in”也可以換成“<>”。
方案2
通過查找資料發現mysql有這么個函數:field
通俗來說field函數一般這樣用
field(id, 'str1', 'str2', 'str3')
在字段id中搜索,如果和str1相同,則返回1,以此類推分別返回1,2,3...沒有匹配到的返回0,可以做個小實驗
select field(product_id, 2,6,8),product_id,name from product limit 10
這樣看起來就明顯多了。網上的資料顯示我們可以這樣來完成這個排序任務
,比如這里stackoverflow。
然而我這樣寫
select product_id,name from product order by field(product_id, 2,6,8) limit 10
得到的結果卻是這樣的
仔細想想,order by 默認的是asc,所以field返回是0的都排在了前面,而選中的幾個返回了1,2,3排在了后面。那么我們把asc改成desc
select product_id,name from product order by field(product_id, 2,6,8) desc limit 10
結果還是和預期不同,仔細看圖2,原來無論我們用desc還是asc都無法把排序變成1230000...,所以這個field在這種場景下是無法滿足要求的。
順便提一下,這兩種寫法
select 1,2,product_id,name from product limit 10
select product_id,name from product order by 2 limit 10
這兩種寫法都很坑爹,但是還是可以了解下的,第一種寫法就是在查詢出來的數據的基礎上加一列“常數”,比如序號什么的,第二種寫法中order by 2 是按第二個字段排序(我也是剛知道,原來字段的順序還真有用),不信你把order by 2 改成 order by 1和order by 字段數+1試試。
方案3
也是用mysql自帶的一個函數,locate
locate(substr, str)返回子串substr在字符串str中第一次出現的位置
同樣,先來個測試
select locate(product_id, '2,6,8'),product_id,name from product order by 2 limit 10
這里返回的是1,3,5,因為逗號也算在內了,之所以不用‘268’做為字符串是為了避開26,268,這類id。
看到這個測試之后,我想不用再繼續下去了,后續同方案2。
最后總結一句話就是:還是方案1簡單粗暴。