欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-10-31 22:33:31
接上篇sql 排序,排序后,可查出上下条数据。 Row_Number() 函数给表添加了一列序列号且不重复,即可根据当前数据对应的值,找上下条数据。 依旧是上文的例子,如下图,...

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

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

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

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

实现:

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查出某行数据的上下条数据的方法

显然,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'
)

结果:

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

也是查到了工单为‘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 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾