2011-06-29 68 views
0

任何人都可以指向一個CTE被用來逐步通過記錄集而不是光標的例子嗎?CTE而不是光標

我已經能夠找到的所有示例顯示遞歸。我不需要那個。我只想一次一步地完成一個記錄集。

謝謝。

(編輯)

也許這是最好的問另一種方式。我假設CTE或光標可能是獲取我想要的數據的最佳方式,但這裏是一個示例。

如果我有一個與userids,代碼和日期如下表,其中userid不是一個主鍵。

 
2011-05-24 11:06:28.080  CODE1 199 
2011-05-24 11:06:28.080  CODE2 199 
2011-06-08 13:30:14.830  CODE2 209 
2011-06-08 13:30:14.313  CODE1 209 
2011-06-08 13:30:13.840  CODE2 209 
2011-06-08 13:30:13.450  CODE1 209 
2011-06-08 13:30:13.050  CODE2 209 
2010-05-07 10:45:06.800  CODE3 79 
2010-05-07 10:45:04.833  CODE3 79 
2010-10-15 07:30:16.193  CODE3 79 
2010-01-26 13:51:43.923  CODE3 79 
2010-01-26 13:51:43.923  CODE3 79 
2010-01-26 13:51:44.427  CODE3 79 
2010-01-26 13:51:45.103  CODE3 79 
2010-01-26 13:51:45.890  CODE3 79 
2010-01-26 13:51:46.733  CODE3 79 
2010-01-25 12:40:39.737  CODE3 81 
2010-01-25 12:40:40.890  CODE3 81 
2010-01-25 12:40:41.627  CODE3 81 
2010-01-25 12:40:43.277  CODE3 81 
2010-01-25 14:29:08.360  CODE3 81 
2010-01-21 19:36:34.660  CODE3 98 
2010-01-21 19:36:34.843  CODE3 98 
2010-01-21 19:36:35.013  CODE3 98 
2010-01-21 22:27:24.317  CODE3 83 
2010-01-21 22:31:21.443  CODE2 83 
2010-01-22 19:44:28.880  CODE3 83 

我想從該表中選擇最早的日期和代碼爲每個用戶是有可能做到這一點使用CTE?

我可以做一個選擇,我通過customerid進行分組並獲得MIN(datefield),但是我得不到與那個最早的日期相關的代碼,除非我將它添加到我的group by子句中,然後當然,我爲客戶獲得多行,每行都有相關的代碼。

我發現了一個解決方案,該解決方案適用於創建臨時表並通過在customerid上進行分組來填充MIN(日期)和客戶ID的解決方案。然後,我通過將客戶和日期字段連接到原始表來將該臨時表更新爲與該行關聯的代碼...但這似乎是一種破解。

我想知道如果通過原始表循環(按customerid和日期排序),每次我看到一個新的客戶ID插入記錄到臨時表中,將是一個更清潔的解決方案...尤其是因爲解決方案我發現假設獨特的日期/客戶組合。

下面是我現在使用的一個示例。這看起來像一個黑客,我想知道是否一個cusor(我通常避免)或CTE是一個更清潔的解決方案。

DECLARE @Table1 TABLE 
(
    ClaimDate datetime, 
    VenueCode nvarchar(50), 
    CustomerID int 
) 
INSERT INTO @Table1 
    SELECT sc.CreateDate, v.code, sc.CSFCustomerID 
    FROM foo join foo1 on (snip) 


DECLARE @Table2 TABLE 
    ( 
    ClaimDate datetime, 
    VenueCode nvarchar(50), 
    CustomerID int) 



INSERT INTO @Table2 
    select MIN(ClaimDate), NULL, CustomerID from @Table1 group by CustomerID 

    UPDATE ft 
    SET ft.SomeCode = t.VenueCode 
FROM @Table2 ft 
INNER JOIN @Table1 t ON ft.CustomerID = t.CustomerID 
AND ft.ClaimDate = t.ClaimDate 

謝謝,我保證我會更好地選擇答案在未來。

+1

CTE不是遊標的替代品。它們更多是臨時表的替代品。例如,如果您需要在每次迭代中執行特定的代碼,那麼CTE不會有太大的幫助。 –

+3

爲什麼你需要一次一個「一步一步」?你爲什麼認爲任何類型的逐行操作(不管它是否聲明DECLARE CURSOR)將執行與光標不同的任何操作?減慢它的是逐行部分,而不是DECLARE CURSOR部分。 –

+1

是的,請解釋您的用例,我們可以指出您的解決方案。 – JNK

回答

0
with qry 
(
SELECT Min(Date), userID 
FROM TABLE 
GROUP BY UserID 
) 

SELECT Table.* 
FROM TABLE 
INNER JOIN qry on qry.UserID = Table.UserID AND qry.Date = Table.Date 
+0

一旦您添加了VenueCode字段Mitch,您的解決方案就無法工作。不過謝謝。 – BillyPilgrim

+0

那它不起作用? 'SELECT Table。*'行應該返回該表的所有列,包括Code列...... – therealmitchconnors

0

雖然這是很舊的文章和問題的標題是不恰當的,說明你的主要任務,就是最後:我想從該表中選擇最早的日期和代碼爲每個用戶是否可能使用CTE來做到這一點?

答案是。你可以試試這個:

-- CTE version of the SQL 
WITH CTE (OldestClaimData, CustomerID) 
AS 
(
    SELECT 
    MIN(ClaimDate), CustomerID 
    FROM 
    UserClaims 
    GROUP BY 
    CustomerID 
) 
SELECT DISTINCT 
    UC.* 
FROM 
    UserClaims UC 
INNER JOIN 
    CTE ON (
    CTE.OldestClaimData=UC.ClaimDate 
    AND 
    CTE.CustomerID=UC.CustomerID 
    AND 
    UC.VenueCode=(
     SELECT TOP 1 
     VenueCode 
     FROM 
     UserClaims sub 
     WHERE 
     sub.ClaimDate=UC.ClaimDate 
     AND 
     sub.CustomerID=UC.CustomerID 
    ) 
) 
ORDER BY 
    UC.CustomerID; 

我已經把我的代碼和你爲SQL Fiddle爲您提供方便。

P.D.:在您的工作accept rate