Заменить курсор SQL Server 2005 - PullRequest
3 голосов
/ 22 августа 2011

Вот упрощенный курсор:

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.

Спасибо.

Ответы [ 2 ]

4 голосов
/ 22 августа 2011

Конечно - довольно просто - используйте CTE (Common Table Expression), который разбивает ваши данные по набору «группировки».

;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

0 голосов
/ 22 августа 2011

Один из возможных методов:

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, что противоречит правилам нормализации для реляционной базы данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...