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)

优化后的代码:

 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

问题,最初版本中的代码中datediff函数计算值怎样用一个临时变量存起来供后面使用,而不是重新计算。不知道这样写在存储过程中会不会有性能损失(理论上的)。

网上其它相关解决方案:

关于union all中使用多个order by 子句引起的问题

http://blog.chinaunix.net/uid-20449297-id-1676810.html

UNION ALL 子句不能包含ORDER BY的解决之道

http://www.itpub.net/thread-1718235-1-1.html

union all和order by一起使用出问题

http://blog.csdn.net/tobeistdo/article/details/5613888

order by 和union all 如何共存

http://zhidao.baidu.com/link?url=GNpYMvin_xvKTQWrLMwHuoWg1yJtt0HODDLQYclj-tEuHJubI9UCJ4Uvm6qnP5eJL1sz8nKrKjM69OFHLGZcYq

来自为知笔记(Wiz)

时间: 2024-10-13 22:25:57

SQL 语句中union all和order by同时使用的相关文章

SQL语句中:UNION与UNION ALL的区别

UNION用的比较多union all是直接连接,取到得是所有值,记录可能有重复 union 是取唯一值,记录没有重复 1.UNION 的语法如下: [SQL 语句 1] UNION [SQL 语句 2] 2.UNION ALL 的语法如下: [SQL 语句 1] UNION ALL [SQL 语句 2] 效率:UNION和UNION ALL关键字都是将两个结果集合并为一个,但这两者从使用和效率上来说都有所不同. 1.对重复结果的处理:UNION在进行表链接后会筛选掉重复的记录,Union Al

获取oracle sql语句中绑定变量值的方法

在诊断 sql的性能问题时,我们有时候需要获取其绑定变量的实际值,然后将此实际值带入到sql语句当中,用原来的sql构成select语句(带where条件),实际的执行一下,看一下选择性如何. 本文就是说获取其绑定变量值的方法.本文的编写得到枯荣长老的帮助,在此表示感谢. 本文适用于与oracle 10G或者更高版本的db. alter session set nls_date_format = 'yyyy-mm-dd,hh24:mi:ss'; set linesize 400 col sql_

SQL语句中的乘号

在ADO中,我们需要在SQL语句中使用乘法运算,可是添加'*'以后执行程序总是会出错,这是因为‘*’与sql中的‘*’关键字重合了,所以编译会出错. 解决办法:将乘法运算放到sql语句外面,将结果放入一个变量中,然后在sql语句中引用即可 int count = (this.AspNetPager1.CurrentPageIndex-1)*this.AspNetPager1.PageSize; string sql = " select top "+count+" E_Id

LINQ体验(8)——LINQ to SQL语句之Union All/Union/Intersect和Top/Bottom和Paging和SqlMethods

我们继续解说LINQ to SQL语句,这篇我们来讨论Union All/Union/Intersect操作和Top/Bottom操作和Paging操作和SqlMethods操作 . Union All/Union/Intersect操作 适用场景:对两个集合的处理,比如追加.合并.取同样项.相交项等等. Concat(连接) 说明:连接不同的集合.不会自己主动过滤同样项:延迟. 1.简单形式: var q = ( from c in db.Customers select c.Phone ).

sql语句中#{}和${}的区别

#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号.如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id". $将传入的数据直接显示生成在sql中.如:order by userid,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id.

SQL语句中的select高级用法

为了更好的了解下面的知识点,我们先创建两张表并插入数据. # 学生表 +----+-----------+------+--------+--------+--------+-----------+ | id | name | age | height | gender | cls_id | is_delete | +----+-----------+------+--------+--------+--------+-----------+ | 1 | 小明 | 18 | 180.00 | 女

sql 语句中count()有条件的时候为什么要加上or null

参考:https://blog.csdn.net/qq_32719287/article/details/79513164 1.sql 语句中count()有条件的时候为什么要加上or null. 如count(province = '浙江' or NULL) 这部分,为什么要加上or NULL,直接count(province='浙江')有什么问题吗?不就是要找province = '浙江'的数据吗,为什么要计算NULL的数据. 答案:因为当 province不是浙江时 province='浙

COMMENT方法 用于在生成的SQL语句中添加注释内容,

COMMENT方法 用于在生成的SQL语句中添加注释内容,例如: $this->comment('查询考试前十名分数') ->field('username,score') ->limit(10) ->order('score desc') ->select(); 复制代码 大理石平台知识 最终生成的SQL语句是: SELECT username,score FROM think_score ORDER BY score desc LIMIT 10 /* 查询考试前十名分数

回顾sql语句中的各种连接

1. 内连接(Inner Join) 内连接是最常见的一种连接,它页被称为普通连接,而E.FCodd最早称之为自然连接. 下面是ANSI SQL-92标准 select * from    t_institution i inner join t_teller t on i.inst_no = t.inst_no where i.inst_no = "5801" 其中inner可以省略. 等价于早期的连接语法 select * from t_institution i, t_telle