最近也是在寫項目中碰到的這個問題,需要將兩個SELECT查詢結果組合起來進行分組排序,想到了用union方法,用TP的union操作根本無法完成復雜的union操作,於是搜羅了一下,先說一下union的用法,在說一下TP中如何實現復雜的union操作。
一、UNION 用法
一 UNION語法
SELECT ...
UNION[ALL | DISTINCT]
SELECT ...
[UNION [ALL | DISTINCT]
SELECT ...]
UNION用於把來自許多SELECT語句的結果組合到一個結果集合中。
列於每個SELECT語句的對應位置的被選擇的列應具有相同的類型。(例如,被第一個語句選擇的第一列應和被其它語句選擇的第一列具有相同的類型。www.111cn.net)在第一個SELECT語句中被使用的列名稱也被用於結果的列名稱。
SELECT語句為常規的選擇語句,但是受到如下的限定:
·只有最後一個SELECT語句可以使用INTO OUTFILE。
·HIGH_PRIORITY不能與作為UNION一部分的SELECT語句同時使用。如果您對第一個 SELECT指定了HIGH_PRIORITY,則不會起作用。如果您對其它後續的SELECT語句指定了HIGH_PRIORITY,則會產生語法錯誤。
如果您對UNION不使用關鍵詞ALL,則所有返回的行都是唯一的,如同您已經對整個結果集合使用了DISTINCT。如果您指定了ALL,您會從所有用過的SELECT語句中得到所有匹配的行。
DISTINCT關鍵詞是一個自選詞,不起任何作用,但是根據SQL標准的要求,在語法中允許采用。(在MySQL中,DISTINCT代表一個共用體的默認工作性質。)
您可以在同一查詢中混合UNION ALL和UNION DISTINCT。被混合的UNION類型按照這樣的方式對待,即DISTINCT共用體覆蓋位於其左邊的所有ALL共用體。DISTINCT共用體可以使用UNION DISTINCT明確地生成,或使用UNION(後面不加DISTINCT或ALL關鍵詞)隱含地生成。
如果您想使用ORDER BY或LIMIT子句來對全部UNION結果進行分類或限制,則應對單個地SELECT語句加圓括號,並把ORDER BY或LIMIT放到最後一個的後面。以下例子同時使用了這兩個子句:
(SELECT a FROM tbl_name WHERE a=10 AND B=1)UNION(SELECT a FROM tbl_name WHERE a=11 AND B=2)ORDER BY a LIMIT 10;
(SELECT a FROM tbl_name WHERE a=10 AND B=1)UNION(SELECT a FROM tbl_name WHERE a=11 AND B=2)ORDER BY a LIMIT 10;
這種ORDER BY不能使用包括表名稱(也就是,采用tbl_name.col_name格式的名稱)列引用。可以在第一個SELECT語句中提供一個列別名,並在ORDER BY中參閱別名,或使用列位置在ORDER BY中參閱列。(首選采用別名,因為不建議使用列位置。)
另外,如果帶分類的一列有別名,則ORDER BY www.111cn.nEt子句必須引用別名,而不能引用列名稱。以下語句中的第一個語句必須運行,但是第二個會運行失敗,出現在'order clause'中有未知列'a'的錯誤:
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b;
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;
To apply ORDER BY or LIMIT to an individual SELECT, place the clause inside the parentheses that enclose the SELECT。
為了對單個SELECT使用ORDER BY或LIMIT,應把子句放入圓括號中。圓括號包含了SELECT。
代碼如下 復制代碼(SELECT a FROM tbl_name WHERE a=10 AND B=1 ORDER BY a LIMIT 10)UNION(SELECT a FROM tbl_name WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
二 實例擴展
union可以對同一個表的兩次查詢聯合起來. 這樣做的益處也非常明顯, 比如在blog應用中, 可以利用一條sql語句實現置頂blog和普通blog的分頁顯示.
代碼如下 復制代碼 (注:union要求聯合的兩個表所要查找的數據列要一樣多,如果一個表中沒有另一個表的字段,可以用NULL代替
三,實例
UNION
代碼如下 復制代碼select * from
(
select * from ...
union all
select * from ...
) aaa
order by aaa.xxx desc;
中的UNION
UNION在進行表鏈接後會篩選掉重復的記錄,所以在表鏈接後會對所產生的結果集進行排序運算,刪除重復的記錄再返回結果。實際大部分應用中是不會產生重復的記錄,最常見的是過程表與歷史表UNION。如:
select * from gc_dfys union select * from ls_jg_dfys
這個SQL在運行時先取出兩個表的結果,再用排序空間進行排序刪除重復的記錄,最後返回結果集,如果表數據量大的話可能會導致用磁盤進行排序。
MySQL中的UNION ALL
而UNION ALL只是簡單的將兩個結果合並後就返回。這樣,如果返回的兩個結果集中有重復的數據,那麼返回的結果集就會包含重復的數據了。
從效率上說,UNION ALL 要比UNION快很多,所以,如果可以確認合並的兩個結果集中不包含重復的數據的話,那麼就使用UNION ALL,如下:
select * from gc_dfys union all select * from ls_jg_dfys
解決mysql中union排序的問題 .
關於union雙向排序(mysql)
群裡的朋友問了一個mysql查詢的問題
需求是這樣的
論壇希望在顯示帖子列表時侯前三條是點擊量最多的,即按點擊次數查詢,
余下的按時間查詢
實際就是兩個union的排序都生效
Sql代碼
代碼如下 復制代碼(select * from (select * from table order by colnum desc) a);
(select * from table order by colnum limit 0,2
)
UNION (select * from (select * from table order by colnum desc) a);
估計很多人會有這個需求。
代碼如下 復制代碼 SELECT *,1 as ord FROM `women` where status = 2 and title like '%2014%' or title like '%秋冬%' union (select *,2 as ord FROM `women` where status = 2 and keywords like '%2014%' or keywords like '%秋冬%') ORDER BY ord,id desc limit 0,15;