[英]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
和更新CovEndDate
在EligCov
表(总一行特定groupno/ssn
组合)。
payroll
表有10,000,000多行, EligCov
表有大约200,000行。 有没有办法改变这个不使用游标?
要重申,对每个group/ssn
在EligCov
通过所有的记录看Payroll
与同group/ssn
和抢max(CovEndDate)
和更新CovEndDate
在EligCov
表。
谢谢。
当然 - 非常简单 - 使用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.