UNION 用于将多个 SELECT 语句的结果合并到结果集中。第一个 SELECT 语句的列名被用作返回结果的列列名。在每个 SELECT 语句的相应位置列出的选定列应该有相同的数据类型。
测试数据和表结构
1 2 3 4 5 6 7 8 9 10
mysql>desc books; +-------------+---------------------+------+-----+---------+----------------+ | Field | Type |Null| Key |Default| Extra | +-------------+---------------------+------+-----+---------+----------------+ | id |int(10) unsigned |NO| PRI |NULL| auto_increment | | name |varchar(255) |NO||NULL|| | create_time | datetime |NO||NULL|| | is_hot | tinyint(3) unsigned |NO||0|| +-------------+---------------------+------+-----+---------+----------------+ 4rowsinset (0.00 sec)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
mysql>select*from books; +----+---------------------------------------+---------------------+--------+ | id | name | create_time | is_hot | +----+---------------------------------------+---------------------+--------+ |1| Head First Java |2017-12-0417:19:36|0| |2| Think in Java |2017-12-0217:19:36|0| |3| Clean Code |2017-12-0117:19:36|0| |4| The Ruby Programming |2017-12-0517:19:36|1| |5| JavaScript Definitive Guides |2017-12-0617:19:36|0| |6| Java 9 Data Structures and Algorithms |2017-12-0717:19:36|1| |7| The C Programming Language|2017-12-0817:19:36|0| |8| Pro Spring Boot |2017-12-0917:19:36|1| +----+---------------------------------------+---------------------+--------+ 8rowsinset (0.00 sec)
组合查询
where 和 union 语句在多数情况下可以实现相同的结果集。where 可以实现的语句,一定可以用 union 实现。而 union 可以实现的语句,where 却不一定能做到。因为,union 是可以针对多张表进行结果集的合并。 查询 id = 1 的记录
1 2 3 4 5 6 7
mysql>select*from books where id =1; +----+-----------------+---------------------+--------+ | id | name | create_time | is_hot | +----+-----------------+---------------------+--------+ |1| Head First Java |2017-12-0417:19:36|0| +----+-----------------+---------------------+--------+ 1rowinset (0.00 sec)
查询 is_hot = 1 的记录
1 2 3 4 5 6 7 8 9
mysql>select*from books where is_hot =1; +----+---------------------------------------+---------------------+--------+ | id | name | create_time | is_hot | +----+---------------------------------------+---------------------+--------+ |4| The Ruby Programming |2017-12-0517:19:36|1| |6| Java 9 Data Structures and Algorithms |2017-12-0717:19:36|1| |8| Pro Spring Boot |2017-12-0917:19:36|1| +----+---------------------------------------+---------------------+--------+ 3rowsinset (0.00 sec)
使用 union 合并两个查询
1 2 3 4 5 6 7 8 9 10
mysql>select*from books where id =1unionselect*from books where is_hot =1; +----+---------------------------------------+---------------------+--------+ | id | name | create_time | is_hot | +----+---------------------------------------+---------------------+--------+ |1| Head First Java |2017-12-0417:19:36|0| |4| The Ruby Programming |2017-12-0517:19:36|1| |6| Java 9 Data Structures and Algorithms |2017-12-0717:19:36|1| |8| Pro Spring Boot |2017-12-0917:19:36|1| +----+---------------------------------------+---------------------+--------+ 4rowsinset (0.00 sec)
当然,我们通过 select * from books where id = 1 or is_hot = 1 也可以做到,但是 union 是不限于表的。也就是说,我们可以从多个表中查询结果集出来,然后 merge 到第一个查询语句查询的结果集中(前提是字段数量和类型一致)。
重复项
默认情况下,我们单单使用 union 语句,会自动帮我们去除重复的项。但是,如果我们使用了 union all 语句,数据库不会帮我们自动去除重复项。
1 2 3 4 5 6 7 8 9 10
mysql>select*from books where id >5unionselect*from books where is_hot =1; +----+---------------------------------------+---------------------+--------+ | id | name | create_time | is_hot | +----+---------------------------------------+---------------------+--------+ |6| Java 9 Data Structures and Algorithms |2017-12-0717:19:36|1| |7| The C Programming Language|2017-12-0817:19:36|0| |8| Pro Spring Boot |2017-12-0917:19:36|1| |4| The Ruby Programming |2017-12-0517:19:36|1| +----+---------------------------------------+---------------------+--------+ 4rowsinset (0.00 sec)
1 2 3 4 5 6 7 8 9 10 11 12
mysql>select*from books where id >5unionallselect*from books where is_hot =1; +----+---------------------------------------+---------------------+--------+ | id | name | create_time | is_hot | +----+---------------------------------------+---------------------+--------+ |6| Java 9 Data Structures and Algorithms |2017-12-0717:19:36|1| |7| The C Programming Language|2017-12-0817:19:36|0| |8| Pro Spring Boot |2017-12-0917:19:36|1| |4| The Ruby Programming |2017-12-0517:19:36|1| |6| Java 9 Data Structures and Algorithms |2017-12-0717:19:36|1| |8| Pro Spring Boot |2017-12-0917:19:36|1| +----+---------------------------------------+---------------------+--------+ 6rowsinset (0.00 sec)
关于排序
union 中的排序是比较坑的,即使我们在部分结果集这种写了 order by 语句。因为,union 会在合并结果集之后自动的进行排序。意味着在子结果集中的排序,排了也是白排。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
mysql> (select*from books where is_hot =1orderby create_time desc) ->union -> (select*from books where is_hot =0orderby create_time desc); +----+---------------------------------------+---------------------+--------+ | id | name | create_time | is_hot | +----+---------------------------------------+---------------------+--------+ |4| The Ruby Programming |2017-12-0517:19:36|1| |6| Java 9 Data Structures and Algorithms |2017-12-0717:19:36|1| |8| Pro Spring Boot |2017-12-0917:19:36|1| |1| Head First Java |2017-12-0417:19:36|0| |2| Think in Java |2017-12-0217:19:36|0| |3| Clean Code |2017-12-0117:19:36|0| |5| JavaScript Definitive Guides |2017-12-0617:19:36|0| |7| The C Programming Language|2017-12-0817:19:36|0| +----+---------------------------------------+---------------------+--------+ 8rowsinset (0.00 sec)