图片 9

Mysql中UNION用法与排序

创建一个测试数据表

   最近也是在写项目中碰到的这个问题,需要将两个SELECT查询结果组合起来进行分组排序,想到了用union方法,用TP的union操作根本无法完成复杂的union操作,于是搜罗了一下,先说一下union的用法,在说一下TP中如何实现复杂的union操作。

CREATE TABLE `temp_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `endtime` int(10) NOT NULL,
  `basic_sort` smallint(8) NOT NULL,
  `type` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

  一、UNION 用法

对UNION 和UNION ALL 进行比较:

  一 UNION语法

在MySQL
5.1中文手册中有下面一句话:

  SELECT …

如果您对UNION不使用关键词ALL,则所有返回的行都是唯一的,如同您已经对整个结果集合使用了DISTINCT。如果您指定了ALL,您会从所有用过的SELECT语句中得到所有匹配的行。

  UNION[ALL | DISTINCT]

插入测试数据:

  SELECT …

INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('a', '1534349307', '10', '2');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('a', '1534349308', '14', '2');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('c', '1534349309', '12', '1');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('d', '1534349310', '12', '1');

  [UNION [ALL | DISTINCT]

 图片 1

  SELECT …]

(SELECT id,name,endtime,basic_sort,type from temp_table where type=1)
UNION 
(SELECT id,name,endtime,basic_sort,type from temp_table where type=2);

  UNION用于把来自许多SELECT语句的结果组合到一个结果集合中。

 

  列于每个SELECT语句的对应位置的被选择的列应具有相同的类型。(例如,被第一个语句选择的第一列应和被其它语句选择的第一列具有相同的类型。www.111cn.net)在第一个SELECT语句中被使用的列名称也被用于结果的列名称。

(SELECT id,name,endtime,basic_sort,type from temp_table where type=1)
UNION ALL
(SELECT id,name,endtime,basic_sort,type from temp_table where type=2);

  SELECT语句为常规的选择语句,但是受到如下的限定:

 对于上面两句分别是UNION和UNION ALL组合,但是得到的结果是一致的。

  ·只有最后一个SELECT语句可以使用INTO OUTFILE。

图片 2

  ·HIGH_PRIORITY不能与作为UNION一部分的SELECT语句同时使用。如果您对第一个
SELECT指定了HIGH_PRIORITY,则不会起作用。如果您对其它后续的SELECT语句指定了HIGH_PRIORITY,则会产生语法错误。

其实上面说的【所有返回的行都是唯一的】这里所说的是主键唯一:

  如果您对UNION不使用关键词ALL,则所有返回的行都是唯一的,如同您已经对整个结果集合使用了DISTINCT。如果您指定了ALL,您会从所有用过的SELECT语句中得到所有匹配的行。

(SELECT id,name,endtime,basic_sort,type from temp_table)
UNION 
(SELECT id,name,endtime,basic_sort,type from temp_table);

  DISTINCT关键词是一个自选词,不起任何作用,但是根据SQL标准的要求,在语法中允许采用。(在MySQL中,DISTINCT代表一个共用体的默认工作性质。)

图片 3

  您可以在同一查询中混合UNION ALL和UNION
DISTINCT。被混合的UNION类型按照这样的方式对待,即DISTINCT共用体覆盖位于其左边的所有ALL共用体。DISTINCT共用体可以使用UNION
DISTINCT明确地生成,或使用UNION(后面不加DISTINCT或ALL关键词)隐含地生成。

(SELECT id,name,endtime,basic_sort,type from temp_table)
UNION ALL
(SELECT id,name,endtime,basic_sort,type from temp_table);

  如果您想使用ORDER
BY或LIMIT子句来对全部UNION结果进行分类或限制,则应对单个地SELECT语句加圆括号,并把ORDER
BY或LIMIT放到最后一个的后面。以下例子同时使用了这两个子句:

图片 4

 代码如下

这里对于UNION返回的结果相当于对主键做一次DISTINCT,而UNION
ALL 返回的结果相当于是单纯把结果查询出来然后合并返回。

 

对UNION查询结果进行排序:

(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;   

插入测试数据(将刚刚的表内容删减,使用TRUNCATE `temp_table`):

 (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;

INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('a', '1534349307', '10', '2');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('b', '1534349308', '14', '2');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('c', '1534349309', '12', '2');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('d', '1534349310', '12', '2');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('e', '1534349311', '18', '2');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('f', '1534349312', '18', '2');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('aa', '1534349313', '11', '1');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('bb', '1534349314', '11', '1');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('cc', '1534349315', '13', '1');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('dd', '1534349316', '12', '1');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('ee', '1534349317', '12', '1');
INSERT INTO `temp_table` (`name`,`endtime`,`basic_sort`,`type`) VALUES ('ff', '1534349318', '15', '1');

  这种ORDER
BY不能使用包括表名称(也就是,采用tbl_name.col_name格式的名称)列引用。可以在第一个SELECT语句中提供一个列别名,并在ORDER
BY中参阅别名,或使用列位置在ORDER
BY中参阅列。(首选采用别名,因为不建议使用列位置。)

图片 5

  另外,如果带分类的一列有别名,则ORDER BY
www.111cn.nEt子句必须引用别名,而不能引用列名称。以下语句中的第一个语句必须运行,但是第二个会运行失败,出现在’order
clause’中有未知列’a’的错误:

这里我们想要得到的结果是:按type的正序排序,接着按basic_sort倒叙排序

 代码如下

(select * from temp_table where type=1 ORDER BY basic_sort desc) 
union 
(select * from temp_table where type=2 ORDER BY basic_sort desc)

 

 对于这样的SQL语句得到的结果是:

(SELECT a AS b FROM t) UNION (SELECT …) ORDER BY b; 

图片 6

(SELECT a AS b FROM t) UNION (SELECT …) ORDER BY a; 

与没有在子句中使用ORDER BY的结果一致。

To apply ORDER BY or LIMIT to an individual SELECT, place the clause
inside the parentheses that enclose the SELECT。

(select * from temp_table where type=1) union (select * from temp_table where type=2)

  为了对单个SELECT使用ORDER
BY或LIMIT,应把子句放入圆括号中。圆括号包含了SELECT。

 在MySQL
5.1中文手册中有下面两句话:

 代码如下

1、如果您想使用ORDER
BY或LIMIT子句来对全部UNION结果进行分类或限制,则应对单个地SELECT语句加圆括号,并把ORDER
BY或LIMIT放到最后一个的后面。

 

 如果要完成上面的需求应该是:

(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);

(select *,type as sort_type,basic_sort as sort_value from temp_table) 
union 
(select *,type as sort_type,basic_sort as sort_value from temp_table) 
order by sort_type ASC,sort_value ASC

  二 实例扩展

图片 7

  union可以对同一个表的两次查询联合起来. 这样做的益处也非常明显,
比如在blog应用中, 可以利用一条sql语句实现置顶blog和普通blog的分页显示.

2、圆括号中用于单个SELECT语句的ORDER
BY只有当与LIMIT结合后,才起作用。否则,ORDER BY被优化去除。

 代码如下

(select * from temp_table WHERE type=1 ORDER BY basic_sort ASC LIMIT 6)
union 
(select * from temp_table WHERE type=2 ORDER BY basic_sort ASC LIMIT 6)

 

 图片 8

(   
SELECT * FROM `blog`
WHERE top=1   
ORDER BY created DESC   
)   
UNION
(  
SELECT *   
FROM `blog`   
WHERE top = 0   
ORDER BY created DESC   
) LIMIT 2 , 3  

关于这里是可以使用ORDER BY 与LIMIT
共同完成,但是有些时候我们不能在里面用LIMIT
只能在外面用,比如我们做分页,我们并不知道应该在里面LIMIT
多少才对。

  注:union要求联合的两个表所要查找的数据列要一样多,如果一个表中没有另一个表的字段,可以用NULL代替

 

  三,实例

下面这里有个奇怪的需求,我们需要得到下面一个这个列表,首先是按type正序排列,当type为1的时候是按照basic_sort进行正序排列,当type为2的时候按endtime倒叙排列。

  UNION

因为对于type为1的时候我们不需要对endtime进行排序所以我们在type为1的时候设置endtime的值为0,对于type为2的时候我们不需要basic_sort的值进行排序,所以设置basic_sort的值为0。

 代码如下

图片 9

 

(SELECT id,name,endtime,basic_sort,basic_sort as sort_basic_sort,0 as sort_endtime,type,type as sort_type FROM temp_table WHERE type=1)
union 
(SELECT id,name,endtime,basic_sort,0 as sort_basic_sort,endtime as sort_endtime,type,type as sort_type FROM temp_table WHERE type=2)
ORDER BY sort_type ASC,sort_basic_sort ASC,sort_endtime DESC

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;

http://www.bkjia.com/Mysql/730144.htmlwww.bkjia.comtruehttp://www.bkjia.com/Mysql/730144.htmlTechArticle最近也是在写项目中碰到的这个问题,需要将两个SELECT查询结果组合起来进行分组排序,想到了用union方法,用TP的union操作根本无法完成复