2011-06-29 34 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