如何从SQL Server游标返回单行集?

时间:2013-07-05 07:26:41

标签: sql sql-server cursor tempdb

我有一个在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

2 个答案:

答案 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