繁体   English   中英

替换SQL Server 2005游标

[英]Replace SQL Server 2005 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

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

我只是需要选择max(CovEndDate)一定gpno/ssn组合(这可能是从一排或数百个)的Payroll和更新CovEndDateEligCov表(总一行特定groupno/ssn组合)。

payroll表有10,000,000多行, EligCov表有大约200,000行。 有没有办法改变这个不使用游标?

要重申,对每个group/ssnEligCov通过所有的记录看Payroll与同group/ssn和抢max(CovEndDate)和更新CovEndDateEligCov表。

谢谢。

当然 - 非常简单 - 使用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,然后为每组GroupNo,SSN更新EligCov表,仅更新最近的条目

一种可能的方法:

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中使用该列,这违反了关系数据库的规范化规则。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM