替换 SQL Server 2005 游标

发布于 2024-11-30 20:49:23 字数 1561 浏览 0 评论 0原文

这是简化的光标:

SET IMPLICIT_TRANSACTIONS ON

SET @curTemp = CURSOR FAST_FORWARD
FOR
    SELECT gpno, ssn FROM EligCov Group BY gpno, ssn
OPEN @curTemp

-- loop through cursor and build output report table
FETCH NEXT FROM @curTemp INTO @gpno, @ssn
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @trnCnt = @trnCnt + 1

    -- get the max CovEndDate for this group/ssn combo
    SELECT @MaxCovEndDate=MAX(CovEndDate) FROM Payroll WHERE GroupNo=@gpno AND SSN=@ssn
    UPDATE EligCov SET CovEndDate = @MaxCovEndDate WHERE gpno=@gpno AND ssn=@ssn

    -- check transaction counts and commit if needed
    IF @trnCnt % 2000 = 0
    BEGIN
        IF @@TRANCOUNT > 0
        BEGIN
            COMMIT
        END
    END
    FETCH NEXT FROM @curTemp INTO @gpno, @ssn
END
CLOSE @curTemp
DEALLOCATE @curTemp 

SET IMPLICIT_TRANSACTIONS OFF

基本上表 EligCov 有一个不同的 groupNo/SSN 组合。表 Payroll 将有许多 groupno/ssn 组合。 Payroll 表中的每一行都有一个包含日期的 CovEndDate 列。

我只需从 Payroll 中为特定 gpno/ssn 组合(可以是一行或数百行)选择 max(CovEndDate)并更新 EligCov 表中的 CovEndDate(特定 groupno/ssn 组合始终为一行)。

payroll 表有 10,000,000 多行,EligCov 表有约 200,000 行。有没有办法改变它以不使用光标?

重申一下,对于 EligCov 中的每个 group/ssn,请查看 Payroll 中具有相同 group/ssn 的所有记录> 并获取 max(CovEndDate) 并更新 EligCov 表中的 CovEndDate

谢谢。

Here is the simplified cursor:

SET IMPLICIT_TRANSACTIONS ON

SET @curTemp = CURSOR FAST_FORWARD
FOR
    SELECT gpno, ssn FROM EligCov Group BY gpno, ssn
OPEN @curTemp

-- loop through cursor and build output report table
FETCH NEXT FROM @curTemp INTO @gpno, @ssn
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @trnCnt = @trnCnt + 1

    -- get the max CovEndDate for this group/ssn combo
    SELECT @MaxCovEndDate=MAX(CovEndDate) FROM Payroll WHERE GroupNo=@gpno AND SSN=@ssn
    UPDATE EligCov SET CovEndDate = @MaxCovEndDate WHERE gpno=@gpno AND ssn=@ssn

    -- check transaction counts and commit if needed
    IF @trnCnt % 2000 = 0
    BEGIN
        IF @@TRANCOUNT > 0
        BEGIN
            COMMIT
        END
    END
    FETCH NEXT FROM @curTemp INTO @gpno, @ssn
END
CLOSE @curTemp
DEALLOCATE @curTemp 

SET IMPLICIT_TRANSACTIONS OFF

Basically table EligCov has one distinct groupNo/SSN combo. Table Payroll will have many groupno/ssn combinations. Each row in the Payroll table has a CovEndDate column containing a date.

I need to just select the max(CovEndDate) for a certain gpno/ssn combination (this could be from one row or hundreds) from Payroll and update the CovEndDate in the EligCov table (always one row for a specific groupno/ssn combo).

The payroll table has 10,000,000+ rows and the EligCov table has ~200,000 rows. Is there a way to change this to not use a cursor?

To restate, for each group/ssn in EligCov look through all the records in Payroll with the same group/ssn and grab the max(CovEndDate) and update the CovEndDate in the EligCov table.

Thanks.

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

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

发布评论

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

评论(2

有深☉意 2024-12-07 20:49:23

当然 - 非常简单 - 使用 CTE(通用表表达式)按“分组”集对数据进行分区。

;WITH DataToUpdate AS
(
    SELECT  
        GroupNo, SSN, CovEndDate AS 'MaxCovEndDate',
        ROW_NUMBER() OVER(PARTITION BY GroupNo,SSN ORDER BY CovEndDate DESC) AS 'RowNum'
    FROM dbo.Payroll 
UPDATE 
)
UPDATE dbo.EligCov 
SET CovEndDate = d.MaxCovEndDate 
FROM DataToUpdate d
WHERE gpno = d.GroupNo 
  AND ssn = d.SSN 
  AND d.RowNum = 1   -- select the latest date - the one with RowNum = 1

CTE 按 GroupNo,SSN 对数据进行分区 - 因此每组 GroupNo,SSN 都会分配新的 ROW_NUMBER(),从 1 开始。由于行按 CovEndDate DESC 排序,因此最新/最近的 CovEndDate 获取 RowNum = 1

然后,您可以根据该 CTE 更新 EligCov 表,仅获取每组 GroupNo,SSN 的最新条目

Sure - pretty easy - use a CTE (Common Table Expression) that partitions your data by the "grouping" set.

;WITH DataToUpdate AS
(
    SELECT  
        GroupNo, SSN, CovEndDate AS 'MaxCovEndDate',
        ROW_NUMBER() OVER(PARTITION BY GroupNo,SSN ORDER BY CovEndDate DESC) AS 'RowNum'
    FROM dbo.Payroll 
UPDATE 
)
UPDATE dbo.EligCov 
SET CovEndDate = d.MaxCovEndDate 
FROM DataToUpdate d
WHERE gpno = d.GroupNo 
  AND ssn = d.SSN 
  AND d.RowNum = 1   -- select the latest date - the one with RowNum = 1

The CTE partitions your data by GroupNo,SSN - so each group of GroupNo,SSN is handed out new ROW_NUMBER(), starting at 1. Since the rows are sorted by CovEndDate DESC, the latest/most recent CovEndDate gets RowNum = 1.

Based on that CTE, you then update the EligCov table, only taking those most recent entries, for each group of GroupNo,SSN

趁微风不噪 2024-12-07 20:49:23

一种可能的方法:

UPDATE
    EC
SET
    CovEndDate = SQ.CovEndDate
FROM
    EligCov EC
INNER JOIN (
        SELECT gpno, ssn, MAX(CovEndDate) AS max_dt
        FROM Payroll
        GROUP BY gpno, ssn) SQ ON
    SQ.gpno = EC.gpno AND
    SQ.ssn = EC.ssn

更重要的是,我想问是否真的有必要在 EligCov 中包含该列,这违反了关系数据库的规范化规则。

One possible method:

UPDATE
    EC
SET
    CovEndDate = SQ.CovEndDate
FROM
    EligCov EC
INNER JOIN (
        SELECT gpno, ssn, MAX(CovEndDate) AS max_dt
        FROM Payroll
        GROUP BY gpno, ssn) SQ ON
    SQ.gpno = EC.gpno AND
    SQ.ssn = EC.ssn

More importantly though, I'd ask if it's really necessary to have that column in EligCov, which is against rules of normalization for a relational database.

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