我有一个在SQL Server中工作的查询,用于选择一列中的值与另一列中的值之间的差异,但源表中的前两行。源表有三列(PK bigint,Pv float,Cash float)。
当我使用这个查询时,我得到的是一系列单行行集,而不是一个大行集。我可以将这些逐个插入到临时表中,然后从中选择,但这意味着对于大型表,我最终会得到一个大的临时表以及对返回的第一个记录的长延迟。
有没有办法将此查询的结果有效地作为单行集设置?
declare @PK bigint
declare @Pv float
declare @Cash float
declare @Cash_minus_1 float
declare @Cash_minus_2 float
set @Cash_minus_1 = 0
set @Cash_minus_2 = 0
declare myCursor cursor fast_forward
for select PK, Pv, Cash from MyTable order by PK
for read only
open myCursor
fetch next from myCursor
into @PK, @Pv, @Cash
while @@FETCH_STATUS = 0
begin
select @PK, @Pv, @Cash, @Cash_minus_2
set @Cash_minus_2 = @Cash_minus_1
set @Cash_minus_1 = @Cash
fetch next from myCursor
into @PK, @Pv, @Cash
end
close myCursor
deallocate myCursor
答案 0 :(得分:2)
假设SQL Server 2005或更高版本,您可以使用ROW_NUMBER()
和common table expression来正确排列表格:
;With OrderedRows as (
select PK, Pv, Cash,
ROW_NUMBER() OVER (ORDER BY PK) as rn --Is this correct?
from MyTable
)
select or1.PK,or1.Pv,or1.Cash,COALESCE(or2.Cash,0)
from
OrderedRows or1
left join
OrderedRows or2
or1.rn = or2.rn + 2
在上文中,我假设PK
定义了应该考虑行的顺序,这样你问题中的“两行”就更有意义了。
一般来说,游标应该被视为最后的工具。您应该首先尝试制定您的查询,讨论整个结果集应该是什么样子 - 而不是您(如果必须)将如何逐行处理。
答案 1 :(得分:1)
使用ROW_NUMBER
函数为所需顺序的每一行分配数字(因为PK可能有间隙会破坏查询),并将表连接到-2行。
WITH CTE AS
(
SELECT PK, Pv, Cash, ROW_NUMBER() OVER (ORDER BY PK) RN from MyTable
)
SELECT C.PK, C.Pv, C.Cash, C2.Cash AS Cash_Minus_2
FROM CTE C
LEFT JOIN CTE C2 ON C.RN = C2.RN + 2
在SQL Server 2012
中,甚至可以直接使用窗口函数LAG
。
SELECT PK, Pv, Cash, LAG(Cash,2,NULL) OVER (ORDER BY PK) AS Cash_Minus_2
FROM MyTable