SQL 語句中union all和order by同時使用

          最近作的一個財物管理系統中查詢過時或逾期的存儲過程,返回 「財物所屬的案件名稱」,「財物名稱」,「財物編號」,「 過時或逾期時間 」(超期或逾期前7天開始預警)。
遇到「 union all 內不能使用  order by 」的問題,百度了好久,都沒有一個找到一個好的解決方案。最終仍是本身實現了,記錄一下。
 
爲何用存儲過程,非得用union all 而不在程序中拼接表數據?
          這個 存儲過程不是供咱們Web程序使用的,它是提供給運行在服務器上的C/S程序調用( 用來投放到機房外的LED顯示屏 )。
由於這個C/S程序不是咱們寫的,別人要求用存儲過程並一次性返回超期和預期的數據。
當時我正在客戶那裏安裝這個系統,這個功能是客戶臨時加的,因此就匆忙趕了一個,當時沒排序,回來後整理時才遇到這個問題。
涉及到的數據庫表(字段):
 案件表【 AnJian :(Id,案件名稱【anjianmingcheng】)
財物表【 CaiWu :(Id,所屬案件【Id]anjianId】,財物編號【caiwubianhao】,財物名稱【 caiwumingcheng】,保存指定的保存結束時間【caoqi】
財物調用記錄表【 CaiWuDiaoYongJiLu   :(Id,被調用財物Id【caiwuId】,調用時指定的歸還時間【yujingTime】)
注 保存結束時間和調用歸還時間不能爲空,若是是長期會在程序中指定一個超大的時間值(9999/12/30)。
 
最第一版本:
 1 ALTER proc [dbo].[pr_get_time_limit]
 2 
 3 as
 4 
 5 select 
 6     cast(a.anjianmingcheng as varchar(100))  as anjianmingcheng,
 7     cast(c.caiwumingcheng as varchar(100))  as caiwumingcheng,
 8     cast(c.caiwubianhao as varchar(100)) as caiwubianhao,
 9     case 
10         when datediff(day,c.caoqi,getdate())> 0 then '保存超期'+cast(abs(datediff(day,c.caoqi,getdate())) as varchar(50))+''
11         else cast(abs(datediff(day,c.caoqi,getdate())) as varchar(50))+'天后保存超期'
12     end as state,
13     c.caoqi as tagtime 
14 from SACW_CaiWu c 
15 left join SACW_CaiWuDiaoYongJiLu as d on c.Id=d.caiwuId
16 left join SACW_AnJian as a on c.anjianId=a.id
17 where c.jiazhijine>0 and getdate()>dateadd(day,-7,c.caoqi) or  c.kucunshuliang>0 and getdate()>dateadd(day,-7,c.caoqi)
18 
19 union all
20 
21 select 
22     cast(a.anjianmingcheng as varchar(100))  as anjianmingcheng,
23     cast(c.caiwumingcheng as varchar(100))  as caiwumingcheng,
24     cast(c.caiwubianhao as varchar(100))  as caiwubianhao,
25     case 
26         when datediff(day,d.yujingTime,getdate())> 0 then '歸還逾期'+cast(abs(datediff(day,d.yujingTime,getdate())) as varchar(50))+''
27         else cast(abs(datediff(day,d.yujingTime,getdate())) as varchar(50))+'天后歸還逾期'
28     end as state,
29     d.yujingTime as tagtime 
30 from SACW_CaiWuDiaoYongJiLu d 
31 left join SACW_CaiWu c on c.Id=d.caiwuId
32 left join SACW_AnJian as a on c.anjianId=a.id
33 where d.jiazhijine>0 and getdate()> dateadd(day,-7,d.yujingTime) or  d.caiwushuliang>0 and getdate()>dateadd(day,-7,d.yujingTime)
View Code

 

優化後的代碼:
 1 ALTER proc [dbo].[pr_get_time_limit]
 2 
 3 as
 4 
 5 DECLARE @TempTime  datetime
 6 SET @TempTime = DATEADD(DAY,7,GETDATE())
 7 
 8 SELECT 
 9 a.anjianmingcheng as [anjianmingcheng],
10 t.cm as [caiwumingcheng],
11 t.cb as [caiwubianhao],
12 t.tagtime as [tagtime],
13 case 
14     when t.orderby = 0 then 
15         case
16             when t.timeSpan > 0 then '調用逾期'+cast(t.timeSpan as varchar(50))+''
17             --when t.timeSpan = 0 then '即將逾期'
18             else cast(abs(t.timeSpan) as varchar(50))+'天后調用逾期'
19         end
20     else
21         case
22             when t.timeSpan > 0 then '保存超期'+cast(t.timeSpan as varchar(50))+''
23             --when t.timeSpan = 0 then '即將超期'
24             else cast(abs(t.timeSpan) as varchar(50))+'天后保存超期'
25         end
26 end as [state]
27  
28 FROM (
29     select 
30         c.anjianId as aid,
31         cast(c.caiwumingcheng as varchar(100))  as cm,
32         cast(c.caiwubianhao as varchar(100))  as cb,
33         datediff(day,d.yujingTime,getdate()) as timeSpan,
34         d.yujingTime as tagtime,
35         0 as orderby
36     from SACW_CaiWuDiaoYongJiLu d 
37     left join SACW_CaiWu c on c.Id=d.caiwuId
38     where (d.jiazhijine>0 or d.caiwushuliang>0) and @TempTime > d.yujingTime
39 
40     union all
41 
42     select 
43         c.anjianId as aid,
44         cast(c.caiwumingcheng as varchar(100))  as cm,
45         cast(c.caiwubianhao as varchar(100)) as cb,
46         datediff(day,c.caoqi,getdate()) as timeSpan,
47         c.caoqi as tagtime,
48         1 as orderby
49     from SACW_CaiWu c 
50     where (c.jiazhijine>0 or  c.kucunshuliang>0) and @TempTime > c.caoqi
51 ) as t
52 left join SACW_AnJian as a on t.aid=a.id
53 order by t.orderby,t.timeSpan
View Code

 

問題,最第一版本中的代碼中datediff函數計算值怎樣用一個臨時變量存起來供後面使用,而不是從新計算。不知道這樣寫在存儲過程當中會不會有性能損失(理論上的)。

 
網上其它相關解決方案:
關於union all中使用多個order by 子句引發的問題 
 
UNION ALL 子句不能包含ORDER BY的解決之道
 
union all和order by一塊兒使用出問題
 
order by 和union all 如何共存
 
相關文章
相關標籤/搜索