CTE而不是游标

时间:2011-06-29 22:36:42

标签: sql-server common-table-expression

有人能指出我用CTE代替光标的CTE示例吗?

我已经能够找到显示递归的所有示例。我不需要那个。我只是想逐步浏览一个记录集。

感谢。

(编辑)

也许这是最好的另一种方式。我假设CTE或光标可能是获取我想要的数据的最佳方式,但这是一个例子。

如果我有一个包含用户ID,代码和日期的表,如下所示,其中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(日期字段),但我得不能检索与该最早日期相关的代码,除非我将它添加到我的group by子句...然后当然我为客户获取了多行,每行包含一个相关代码。

我找到了一个解决方案,可以在我创建临时表的地方使用MIN(日期)和客户ID填写它,方法是在customerid上进行分组。然后我通过客户和日期字段将它连接到原始表来更新这个临时表,以获得与该行相关联的代码......但这似乎是一个黑客。

我想知道是否循环遍历原始表(按customerid和日期排序)以及每次我看到将该记录插入临时表的新客户ID时,将是一个更清洁的解决方案......特别是因为解决方案我' m found假设一个唯一的datetime / customerid组合。

这是我现在正在使用的一个例子。它看起来像是一个黑客,我想知道一个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

谢谢,我保证将来会更好地选择答案。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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