先說一下背景吧:現(xiàn)在有一張表learn_article,里面有一個字段hot,當(dāng)hot值為1時表示文章置頂,現(xiàn)在要分頁查詢文章列表,要求置頂文章放在最前面然后按id倒序排列,其他文章按id倒序排列。
提到置頂還獲取列表,我當(dāng)然想到使用UNION啦,于是就寫出了下面這個SQL:
SELECT id,hot FROM
((SELECT * FROM learn_article WHERE hot = 1 ORDER BY id DESC)
UNION
(SELECT * FROM learn_article WHERE hot!= 1 ORDER BY id DESC))A
LIMIT 1,10

然而,從結(jié)果也可以看出它不是我想要的結(jié)果,為毛它沒有執(zhí)行ORDER BY id DESC啊!查閱了UNION相關(guān)說明才知道:
聯(lián)合查詢不僅僅是將數(shù)據(jù)集合合并,他并不是將每個子查詢一個一個查詢出來后聯(lián)接在一起,數(shù)據(jù)庫是將整段查詢語句解釋之后統(tǒng)一查詢得到的是整個的數(shù)據(jù)集合。另外order by在一個數(shù)據(jù)集合查詢里也只能被執(zhí)行一次并且要放在最后一個查詢子句后,所以上面查詢子句中的ORDER BY id DESC會被Mysql忽略!
因此,在聯(lián)合查詢里,order by 要寫在最后一個子查詢之后,并且,該排序是對整個聯(lián)合查詢出來的結(jié)果集排序的,并不是只對最后一個子查詢排序,像下面這樣:
SELECT id,hot FROM learn_article WHERE hot = 1
UNION
SELECT id,hot FROM learn_article WHERE hot!= 1
ORDER BY id DESC LIMIT 1,10

但是,這更不是我要的結(jié)果啊??!到底還要我怎樣呢!后來查閱資料發(fā)現(xiàn):在使用UNION連接多個查詢結(jié)果的情況下,想要在每個select子句使用ORDER BY 就需要同時使用limit!這樣的話問題好像就能解決啦:
SELECT id,hot FROM (
(SELECT * FROM learn_article WHERE hot = 1 ORDER BY id DESC LIMIT 0,3)
UNION
(SELECT * FROM learn_article ORDER BY id DESC LIMIT 0,10))A

但是問題來啦,我怎么知道置頂?shù)奈恼虏閹讞l,非置頂?shù)奈恼虏閹讞l呢?那只有再查詢一下置頂文章的條數(shù)啦:
SELECT COUNT(*) FROM learn_article WHERE hot =1
然后再根據(jù)查詢起點(diǎn)offset和查詢條數(shù)limit,計算置頂文章查詢的數(shù)量(tlimit)和非置頂文章的查詢起點(diǎn)(loffset)和查詢數(shù)量(flimit):
int offset = Integer.valueOf(request.getParameter("offset"));
int limit = Integer.valueOf(request.getParameter("limit"));
//查詢置頂文章數(shù)量,置頂文章不超過一頁
int topNum = this.articleService.countTop(params);
int tlimit = topNum ;
int foffset = offset;
int flimit = limit;
if(topNum < offset){
//第二頁以后
offset-=topNum;
tlimit =0;
}else{
//第一頁
flimit = limit - topNum > 0 ? limit - topNum : 0;
tlimit = topNum;
}
然后就將tlimit,foffset,flimit傳到后臺,進(jìn)行查詢:
SELECT id,hot FROM (
(SELECT * FROM learn_article WHERE hot = 1 ORDER BY id DESC LIMIT 0,#{tlimit})
UNION
(SELECT * FROM learn_article ORDER BY id DESC LIMIT #{foffset},#{flimit}))A
這樣就是實(shí)現(xiàn)了文章置頂?shù)姆猪摬樵?,是在太麻煩啦,到是有一種操作簡單的方法就是使用FIND_IN_SET:
SELECT * FROM learn_article ORDER BY FIND_IN_SET(hot,'1') DESC ,id DESC LIMIT 0,10;

但是呢,大家都知道的FIND_IN_SET執(zhí)行效率太低啦,而且費(fèi)內(nèi)存!大家要是有更好的辦法一定要告訴我哦!