2013-07-05 31 views
1

我有一個查詢下面的SQL Server中工作,以選擇一列中的值和另一列中的值之間的差異,但在源表中早兩行。源表有三列(PK bigint,Pv float,現金浮動)。如何從SQL Server光標返回單行集?

當我使用這個查詢時,我得到的是一系列單行行集合,而不是一個大行集合。我可以將這些一個一個地插入臨時表中,然後從中選擇,但這意味着對於大型表而言,我最終會得到一個大的臨時表以及對返回的第一條記錄的長時間延遲。

有沒有什麼方法可以有效地將此查詢的結果作爲單個行集進行後臺處理?

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 
+1

「之前兩行」 - 由於您的'SELECT'沒有ORDER BY子句,因此可以將其指定爲「來自表格中的其他隨機行」。如果您可以告訴我們哪些列*應該*定義順序,例如「早兩行」實際上是有意義的,那麼我們應該可以幫助 –

+0

另外,您能否說出您正在使用的SQL Server版本? –

+0

@Damien_The_Unbeliever 2008 R2。是的,欣賞行順序沒有在查詢中定義,試圖儘可能簡化示例 - 編輯了示例查詢。 –

回答

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定義的順序應該行被認爲是這樣的,以至於你的問題中的「兩行」更有意義。


一般來說,遊標應視爲最後手段的工具。首先,你應該試着制定你的查詢來說明整個結果集應該是什麼樣子 - 而不是你如何(如果你必須的話)會逐行處理。

+0

欣賞關於遊標使用情況的警告,但讓我們假設我有一個很好的理由,爲什麼我需要逐行處理結果集(這個問題背後的真實查詢更加尷尬,不適合自聯接方法)。我想我的問題是關於是否可以將此查詢的結果作爲單個行集返回,而不是以更高效的方式重寫這個簡單的示例查詢。 –

+0

@JonG - 不,沒有辦法(除了你已經繪製過的臨時表/表變量暫存區)生成多個行,這些行是來自多個SQL語句的* same *結果集的一部分 –

+0

好的,謝謝 - 這就是我害怕... –

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 
+0

感謝您的迴應,我很欣賞這個查詢可以重寫的替代形式,但我在這裏具體詢問如何從遊標查詢返回結果行。 –