2013-10-29 160 views
1

我正在建立一個網站,用戶可以在那裏免費創建帖子。他們還可以爲其帖子支付額外的可見性,這意味着付費帖子將首先顯示在搜索結果中。有薪和無薪職位都在同一張表中,並且職位是否支付是從paid_until列中計算得出的,該列僅包含時間戳。MYSQL:加入兩個排序結果集

現在,爲了使分頁變得簡單,我希望能夠從MySQL中獲得一個很好的結果集,而不需要PHP進行額外的排序,最好使用一個查詢。結果集的總限制是20(如每頁20個帖子),它應該首先包含所有付費帖子(最多20個),然後添加20-n個未付費帖子。這兩個子集都應該在其內部的列modified排序。我需要稍後可以通過設置OFFSET跳過相同的結果。

我已經嘗試過JOIN,UNIONGROUP BY的不同變化,但還沒有拿出能產生我想要的結果的解決方案。

是否有某種方式來寫:

(SELECT * FROM tbl_post WHERE paid_until >= :time_stamp ORDER BY modified DESC) 
UNION 
(SELECT * FROM tbl_post WHERE paid_until < :time_stamp ORDER BY modified DESC) 

,這樣它實際上工作,因爲UNION攪亂排序?

+0

你就不能排序的所有帖子'paid_until'?這可能會讓很難只有20個付費職位,但無論如何,如果超過20人支付這個費用呢? – aspyct

回答

1

您可以按UNION查詢的結果是:

(SELECT * FROM tbl_post WHERE paid_until >= :time_stamp) 
UNION 
(SELECT * FROM tbl_post WHERE paid_until < :time_stamp) 
ORDER BY paid_until >= :time_stamp DESC, modified DESC 

重要的是要保持的括號的最後一個子查詢,所以ORDER BY顯然之外的很重要子查詢。否則,SQL將ORDER BY單獨應用於子查詢,然後在執行UNION的過程中再次對它進行排序。

沒有必要在子查詢中排序,只需在最後一步中完成。

但這種查詢可以進一步簡化:

SELECT * FROM tbl_post 
ORDER BY paid_until >= :time_stamp DESC, modified DESC 
LIMIT :pagesize OFFSET :page_times_pagesize 
+0

我曾嘗試在ORDER BY中使用表達式,但無法讓它在之前工作。我想我必須以某種方式得到錯誤的語法,因爲你的例子完美地工作。謝謝! – Schlaus

1

喜歡的東西:

SELECT col1, col2, col3 
FROM ( SELECT *,1 AS SortCol FROM tbl_post WHERE paid_until >= :time_stamp 
      UNION 
      SELECT *,2 AS SortCol FROM tbl_post WHERE paid_until < :time_stamp 
    )AS sub 
ORDER BY SortCol, modified DESC 
+0

這正是我所需要的,但比爾卡爾文的回答是接受了這次的接受,以獲得更簡潔的解決方案。從你的回答,雖然我瞭解使用SortCols。謝謝! – Schlaus

+0

是的,是不是真的在想別的我會更像他的回答,當你不從同一張表中選擇東西時,或者當你必須在不同的領域進行排序時,添加排序列更有用。 –