替换 SQL Server 2005 游标
这是简化的光标:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当然 - 非常简单 - 使用 CTE(通用表表达式)按“分组”集对数据进行分区。
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.
The CTE partitions your data by
GroupNo,SSN
- so each group ofGroupNo,SSN
is handed out newROW_NUMBER()
, starting at 1. Since the rows are sorted byCovEndDate DESC
, the latest/most recentCovEndDate
getsRowNum = 1
.Based on that CTE, you then update the
EligCov
table, only taking those most recent entries, for each group ofGroupNo,SSN
一种可能的方法:
更重要的是,我想问是否真的有必要在 EligCov 中包含该列,这违反了关系数据库的规范化规则。
One possible method:
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.