这是简化的游标:
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,您更新 EligCov
表,仅获取每组 GroupNo,SSN
关于sql - 替换 SQL Server 2005 游标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7152443/