關於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”關鍵詞。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章