今天在写sql的时候,发现有一个需求需要使用union和union all来进行关联查询,需求是这样的,需要查询一个报告列表,展示的规则如下:
1.先展示10天以内的推荐的报告数据
2.然后查询2年以内的报告数据,按时间由近及远进行展示。
这个就有一个问题,用之前的sql是解决不了用户希望的数据的,因为10天以内既有推荐的数据,也有没有推荐的数据,10天以外还有2年的数据
需要查询,所以我就想到了使用union和union all来进行联合查询,总的设计思路是这样的:
a.我先去查询10天以内的推荐数据然后union 10天以内的非推荐的数据 然后union 10天到2年以内的数据
b.然后在按着这个查询结果进行数据展示
写好之后,发现10天以内的推荐数据需要展示在第一个位置,且需要按时间由近及远进行展示,10天以内的非推荐的数据也需要满足时间由近及远,
10天到2年以内的数据也需要满足时间由近及远,所以就涉及到一个oracle 排序的问题。
经过网上查询资料,发现可以使用子查询的结果然后排序来解决,具体sql如下:
select * from (select report_no,recommed,frequecy,status,create_time from t_report order where recommed='1' by create_time desc nulls last ) result1
union
select * from (select report_no,recommed,frequecy,status,create_time from t_report order where recommed='2' by create_time desc nulls last ) result2
union
select * from (select report_no,recommed,frequecy,status,create_time from t_report order where recommed='3' by create_time desc nulls last ) result2
然后完美解决问题。
最后再说一下union和union all的区别:
UNION在进行表连接后会筛选掉重复的记录,所以在表连接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION。
如: select * from test union select * from test_bk这个SQL在运行时先取出两个表的结果,再用排序空间进行排序删除重复的记录,最后返回结果集,如果表数据量大的话可能会导致用磁盘进行排序。
而UNION ALL只是简单的将两个结果合并后就返回。这样,如果返回的两个结果集中有重复的数据,那么返回的结果集就会包含重复的数据了。
从效率上说,UNION ALL 要比UNION快很多。
所以,如果可以确认合并的两个结果集中不包含重复的数据的话,那么就使用UNION ALL,如下: select * from test union all select * from test_bk