1

我在下面有一个查询,可以在 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
4

2 回答 2

2

假设 SQL Server 2005 或更高版本,您可以使用ROW_NUMBER()通用表表达式来适当地排列表:

;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定义了应该考虑行的顺序,这样你的问题中的“早两行”甚至是有意义的。


一般来说,游标应该被视为最后的工具。首先,您应该始终尝试将您的查询表述为讨论整个结果集的外观 - 而不是您(如果必须)如何逐行解决。

于 2013-07-05T07:43:44.210 回答
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
于 2013-07-05T07:42:55.290 回答