在做数据统计的时候,经常遇到奇葩需求,把多个不同表的查询结果放在一个列表里展示。
第一次遇到这样的需求还是在十几年前,当时还是个没有开发经验的小白。接到这个需求的第一个反应是,这怎么可能完成呢。
于是找 Leader,一个同龄人。虽是同龄人,但是人家已经有数年的开发经验。只见她用笔在草稿纸上画画,用了2个关键字就把我征服了。
这两个关键字就是UNION 和 UNION ALL。
一、UNION 和 UNION ALL
在 MySQL 中,我们可以使用 UNION 操作符将多个不同表的查询结果整合在一起。UNION 操作符用于合并两个或多个 SELECT 语句的结果集。每个 SELECT 语句的列数必须相同,并且列的数据类型必须兼容。
举个例子:
假设你有两个表 table1 和 table2,它们的结构如下:
CREATE TABLE table1 ( id INT, name VARCHAR(50));
CREATE TABLE table2 ( id INT, city VARCHAR(50));
我们可以使用如下的 SQL 语句将它们的查询结果合并在一起:
SELECT id, name FROM table1UNIONSELECT id, city FROM table2;
这个查询会将 table1 中的 id 和 name 列与 table2 中的 id 和 city 列整合在一起,并返回一个包含所有结果的结果集。
如果想要包括重复的行,可以使用 UNION ALL,而不是 UNION。
我们还可以把 UNION 后的语句封装成一个单独的表,然后再对这个表进行join 或者条件查询:
select A.* from (SELECT id, name FROM table1UNIONSELECT id, city FROM table2) as Aleft join ... on...where A.id = ...
二、不存在的字段可以无中生有
两个不同的表,在表设计上不一定全部一样。如果一个表中的字段,另一个表中没有,这两个表怎么合并呢?
很好办,无中生有。它没有我们就给它造一个。
比如,在 table1 中有一个字段 name,table2中就没有。table2中有city,但table1中就没有。
select A.* from (SELECT id, name,null as city FROM table1UNIONSELECT id, "" as name, city FROM table2) as A
在 table1 中,设置一个默认值null,并且给这个值起个别名为city。在table2中,设置一个默认值空字符串,并且起个别名为name。这样两个表的字段就对应起来可以合并了。
需要注意的是:不同表的字段要一一对应。在 UNION 联合子句里,它不会帮你把字段对应起来。因此我们在写查询语句的时候,就需要把字段一一对应起来,每个表的字段和第一个的字段看齐,否则容易数据错乱。
比如说,这个查询语句,查出来的字段向第一个表看齐,字段顺序为:id,name,city,age。第二个表的字段顺序错了,name和city字段位置颠倒了,它也不会帮你订正。
select A.* from (SELECT id, name, city, age FROM table1UNIONSELECT id, city, name, null as age FROM table2) as A
因此,UNION 多个表时,一定要把每个表的字段顺序排放好。
三、IF应用
统计数据 IF 少不了。
IF 是 MySQL 中的条件函数,用于在查询中根据条件返回不同的值。它的基本语法如下:
IF(condition, value_if_true, value_if_false)
condition 是一个条件表达式,如果条件为真,则返回 value_if_true,否则返回 value_if_false。
value_if_true 是在条件为真时要返回的值。
value_if_false 是在条件为假时要返回的值。
我们可以使用 IF 函数根据某个条件返回不同的结果:
SELECT IF(score >= 60, 'Pass', 'Fail') AS result FROM students;
上面的查询将返回学生是否及格的结果,如果分数大于等于 60,则返回 'Pass',否则返回 'Fail'。
如果是等于要这么写:
SELECT IF(score= 60, 'Pass', 'Fail') AS result FROM students;
等于无需写双等号。
四、用UNION替代LEFT JOIN
在写一个复杂查询语句的时候,我用了 LEFT JOIN,一个主表 LEFT JOIN 4个子表,查询条件里还有个 IN,IN 的是 UID,最多放10个 UID,目前有3个 UID,每个 UID 36位字符串,千把条的数据几百秒还没查完,实在受不了,就把查询中止了。
怎么办?拆!
把4个子表拆分成4个查询语句,然后用 UNION ALL 连接,最后再进行数据汇总。查询时间立马将为零点几秒。
在做这个统计的时候,我也提出统计的不合理处,但是上头就是要这样做,还觉得高效,没办法,拿人钱财替人做事,那就做吧。
这条仅作参考,毕竟没有相同的业务逻辑。如果遇到 JOIN 表很多,查询数据又非常慢,不妨使用 UNION 替换试试,说不定就解决了性能问题。
领取专属 10元无门槛券
私享最新 技术干货