sql查出某行数据的上下条数据的方法

接上篇sql 排序,排序后,可查出上下条数据。

Row_Number() 函数给表添加了一列序列号且不重复,即可根据当前数据对应的值,找上下条数据。

依旧是上文的例子,如下图,假如要查“工单号为‘order005’的下一条数据”:

实现:

select * from 
(select Date 日期,OrderID 工单号,OrderSeq 工单顺序,Row_Number() over(order by OrderSeq) as 实际顺序 from
	(
	select 'order001' as OrderID,'2018-2-3' as Date, 10 as OrderSeq
	union all select 'order002' as OrderID,'2018-2-3' as Date, 20 as OrderSeq
	union all select 'order003' as OrderID,'2018-2-5' as Date, 30 as OrderSeq
	union all select 'order004' as OrderID,'2018-2-4' as Date, 10 as OrderSeq
	union all select 'order005' as OrderID,'2018-2-4' as Date, 20 as OrderSeq
	) aa 
)bb where  bb.实际顺序 =
	(
	   select bb.实际顺序 + 1 from 
	  (select Date 日期,OrderID 工单号,OrderSeq 工单顺序,Row_Number() over(order by OrderSeq) as 实际顺序 from
			(
			select 'order001' as OrderID,'2018-2-3' as Date, 10 as OrderSeq
			union all select 'order002' as OrderID,'2018-2-3' as Date, 20 as OrderSeq
			union all select 'order003' as OrderID,'2018-2-5' as Date, 30 as OrderSeq
			union all select 'order004' as OrderID,'2018-2-4' as Date, 10 as OrderSeq
			union all select 'order005' as OrderID,'2018-2-4' as Date, 20 as OrderSeq
			) aa 
		)bb where  bb.工单号 ='order005'
	)

结果:

显然,sql语句很繁琐,当然也是因为我没有建表,刨除手写表数据的几行,换上select * from TableName看上去会好很多,(数据库共用我没有添加test表),但即使这样,select嵌套语句多了也是很麻烦的且不易读,下面是优化方法。

敲黑板,划重点

1.实际上,从语句中可以看出有重复的地方,这就可以拿出来放到表变量中。

declare @t table(实际顺序 int)
insert into @t(实际顺序)
(
	select bb.实际顺序 + 1 from 
	  (select Date 日期,OrderID 工单号,OrderSeq 工单顺序,Row_Number() over(order by OrderSeq) as 实际顺序 from
			(
			select 'order001' as OrderID,'2018-2-3' as Date, 10 as OrderSeq
			union all select 'order002' as OrderID,'2018-2-3' as Date, 20 as OrderSeq
			union all select 'order003' as OrderID,'2018-2-5' as Date, 30 as OrderSeq
			union all select 'order004' as OrderID,'2018-2-4' as Date, 10 as OrderSeq
			union all select 'order005' as OrderID,'2018-2-4' as Date, 20 as OrderSeq
			) aa 
		)bb where  bb.工单号 ='order005'
)

结果:

也是查到了工单为‘order005’的下一条数据的实际顺序,这样可以存到变量中,减少select嵌套带来的繁琐,缺点是:表变量实际上使用了临时表,从而增加了额外的I/O开销,因此,表变量的方式并不太适合数据量大且频繁查询的情况,性能上不好,可以用共用表表达式(CET)来优化

2.用共用表表达式(CET)

with t as 
(
	select Date 日期,OrderID 工单号,OrderSeq 工单顺序,Row_Number() over(order by OrderSeq) as 实际顺序 from
	(
	select 'order001' as OrderID,'2018-2-3' as Date, 10 as OrderSeq
	union all select 'order002' as OrderID,'2018-2-3' as Date, 20 as OrderSeq
	union all select 'order003' as OrderID,'2018-2-5' as Date, 30 as OrderSeq
	union all select 'order004' as OrderID,'2018-2-4' as Date, 10 as OrderSeq
	union all select 'order005' as OrderID,'2018-2-4' as Date, 20 as OrderSeq
	) aa 
)
select * from t where (t.实际顺序=(select t.实际顺序 + 1 from t where t.工单号='order005'))

CET语句跟变量表相似,都是来存储一下中间表,但SQL Server 2005在处理公用表表达式的方式上有所不同,效率更高一些,更利于维护。

注意:使用共用表表达式的一些规则,很容易理解,列下来仅供参考。

1.CTE后面必须直接跟使用CTE的SQL语句(如select、insert、update等),否则,CTE将失效。

2.CTE后面也可以跟其他的CTE,但只能使用一个with,多个CTE中间用逗号(,)分隔

3.如果CTE的表达式名称与某个数据表或视图重名,则紧跟在该CTE后面的SQL语句使用的仍然是CTE,当然,后面的SQL语句使用的就是数据表或视图了

4.CTE 可以引用自身,也可以引用在同一 WITH 子句中预先定义的 CTE。不允许前向引用。

5.不能在 CTE_query_definition 中使用以下子句:

(1)COMPUTE 或 COMPUTE BY

(2)ORDER BY(除非指定了 TOP 子句)

(3)INTO

(4)带有查询提示的 OPTION 子句

(5)FOR XML

(6)FOR BROWSE

6. 如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾

(0)
上一篇 2022年3月21日
下一篇 2022年3月21日

相关推荐