CTE代替光标

发布于 2024-11-17 22:36:21 字数 2425 浏览 2 评论 0原文

谁能向我指出一个使用 CTE 而不是游标来逐步浏览记录集的示例?

我能找到的所有示例都显示递归。我不需要那个。我只想一次浏览一个记录集。

谢谢。

(编辑)

也许最好用另一种方式问这个问题。我认为 CTE 或游标可能是获取我想要的数据的最佳方式,但这里有一个例子。

如果我有一个包含用户 ID、代码和日期的表,如下所示,其中用户 ID 不是主键。

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 将该记录插入临时表时是否会是一个更干净的解决方案......特别是因为我找到的解决方案假设独特的日期时间/客户 ID 组合。

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

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

Can anyone point me to an example of a CTE being used to step through a recordset instead of a cursor?

All of the example I've been able to find show recursion. I don't need that. I just want to step through a recordset one at a time.

Thanks.

(EDIT)

Perhaps this is best asked another way. I assumed a CTE or cursor might be the best way to get the data I want but here's an example.

If I have a table with userids, codes and dates like the following, where the userid not a primary key.

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  

And I want to select from this table the oldest date and code for each user is it possible to do this using a CTE?

I can do a select where I group by customerid and get the MIN(datefield) but I get can't retrieve the code associated with that earliest date unless I add it to my group by clause... and then of course I get multiple rows for a customer, one with each associated code.

I found a solution that works where I create a temp table and fill it with the MIN(Date) and customer ID by grouping on the customerid. Then I update this temp table by joining it to the original table by customer and the date field to get the code associated with that row... but this seems to be a hack.

I was wondering if looping through the original table (sorted by customerid and date) and each time I see a new customer id inserting that record into a temp table, would be a cleaner solution... especially since the solution I'm finding assumes a unique datetime/customerid combination.

Here's an example of what I'm using now. It just seems like a hack and I'm wondering if a cusor (which I normally avoid) or a CTE would be a cleaner solution.

  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

Thanks, and I promise I'll be better about selecting answers in the future.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笨笨の傻瓜 2024-11-24 22:36:21
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
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
记忆之渊 2024-11-24 22:36:21

虽然这是相当老的帖子,而且问题标题不适合说明您的主要任务,但最后是:我想从此表中选择每个用户的最旧日期和代码是否可以使用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 中您的方便。

PD:提高接受率

Though it is quite old post and the question title is not appropriate to illustrate your main task, that is finally: And I want to select from this table the oldest date and code for each user is it possible to do this using a CTE?

The answer is yes. You may try this:

-- 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;

I've put my code and yours into an SQL Fiddle for your convenience.

P.D.: work on your accept rate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文