代码的海,就像我们人生一样。努力朝着一个方向前进,总比盲目的随波逐流更能快速有效的到达彼岸。
今天在项目上遇到这样一个问题:当数据源为SQLServer,加上一个不成熟的分页插件时,“union all”与“order by”的亲密接触就会遇到诸多问题。
开发环境如下:
语言:JAVA
框架:spring boot,MyBatis
数据库:SQLServer
一、先来说一下关于SQLServer关键词,“union all”与“order by”的问题:
先来看下一下语句是否存在问题:
select *
from (
select * from abc1
union all
select * from abc2
) t
order by t.xxx
这样的语句,在SQLServer中执行,并不会有什么问题。但是如果以上面的SQL语句为子查询,在外面再包裹一层SQL用作业务处理的话,那么恭喜你,SQLServer会毫不留情的提示你:
除非另外还指定了 TOP 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效。
这时候,只需要在select 后面加上“top 100 PERCENT”,然后在外面包裹一层就可以正常执行了。具体原因可自行百度。
二、再来说一下,按照上面的问题处理好SQL语句后,如果需要分页的话,那么可能问题又来了:
1、先来看下未加分页正确的SQL语句:
SELECT top 100 percent *
from (
select * from abc1
union all
select * from abc2
) t
order by t.CLINICAL_DATE DESC
如果这时候你所用到的分页插件不怎么成熟,那么代码就会变成这样:
WITH query AS (
SELECT TOP 100 PERCENT ROW_NUMBER() OVER (order by xxx) as __row_number__, top 100 percent *
from (
select * from abc1
union all
select * from abc2
) t
order by xxx
) SELECT * FROM query WHERE __row_number__ BETWEEN 1 AND 15 ORDER BY __row_number__
执行的时候,会提示你“top”附近有语法错误,原因是分页插件只判断了在SELECT语句后追加分页属性,而没有判断有top的这种情况。
2、解决办法:
(1)、自用分页插件时,升级分页插件,加上更多、更复杂条件的判断(推荐这种方案,因为以后肯定有更多地方用到);
(2)、手动编写分页代码;
(3)、避免在不了解所使用的分页插件时,并需要排序的情况下使用“union all”关键词。
如果大家有更好的方案,欢迎留言交谈,互相切磋。