关于SQLServer关键词“union all”与“order by”的矛盾

代码的海,就像我们人生一样。努力朝着一个方向前进,总比盲目的随波逐流更能快速有效的到达彼岸。

今天在项目上遇到这样一个问题:当数据源为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”关键词。

如果大家有更好的方案,欢迎留言交谈,互相切磋。

你可能感兴趣的:(sql,server,java,spring,boot,java,sqlserver)