Работа с запросом для архивирования данных клиента - PullRequest
0 голосов
/ 03 октября 2019

У меня есть таблица Customers, таблица Transactions и таблица Payments. Таблица Transactions представляет платежи клиенту, а таблица Payments представляет кредиты покупателю. (Обе таблицы имеют внешние ключи к таблице Customers.)

Баланс клиента рассчитывается с использованием Customers.StartingBalance плюс сумма всех расходов этого клиента в таблице Transactions минус сумма всехплатежи этого клиента в таблице Payments.

Теперь я хочу реализовать функцию архивирования, которая удаляет все транзакции и платежи до определенной даты, а затем обновляет Customers.StartingBalance так, чтобы окончательный баланс (рассчитывался какописанный в предыдущем абзаце) остается прежним.

Вот что я имею до сих пор:

ALTER PROCEDURE [dbo].[ArchiveData] @ArchiveDateTime DATETIME
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @CustomerBalance TABLE
    (
        CustomerId INT,
        Amount BIGINT
    );

    BEGIN TRANSACTION;

    -- Archive transactions
    DELETE Transactions WITH (TABLOCK)
    OUTPUT deleted.CustomerId, deleted.TotalAmount INTO @CustomerBalance
    WHERE [TimeStamp] < @ArchiveDateTime;

    IF EXISTS (SELECT 1 FROM @CustomerBalance)
    BEGIN
        UPDATE Customers SET StartingBalance = StartingBalance +
            (SELECT SUM(Amount) FROM @CustomerBalance cb WHERE Id = cb.CustomerId)
    END;

    DELETE FROM @CustomerBalance

    -- Archive payments
    DELETE Payments WITH (TABLOCK)
    OUTPUT deleted.CustomerId, deleted.Amount INTO @CustomerBalance
    WHERE [Date] < @ArchiveDateTime;

    IF EXISTS (SELECT 1 FROM @CustomerBalance)
    BEGIN
        UPDATE Customers SET StartingBalance = StartingBalance -
            (SELECT SUM(Amount) FROM @CustomerBalance cb WHERE Id = cb.CustomerId)
    END;

    -- Probably not needed
    DELETE FROM @CustomerBalance

    COMMIT TRANSACTION;
END

Поскольку SQL не является моей основной компетенцией, я хотел бы получить отзыв об этом. Это кажется "правильным"? Это кажется оптимальным? Кроме того, я не уверен в таких предложениях, как следующие.

UPDATE Customers SET StartingBalance = StartingBalance -
    (SELECT SUM(Amount) FROM @CustomerBalance cb WHERE Id = cb.CustomerId)
  1. Что это делает, если @CustomerBalance не содержит строк для клиента?

  2. Что это делает, если @CustomerBalance содержит несколько строк для клиента?

Спасибо за любые предложения.

1 Ответ

1 голос
/ 03 октября 2019

О вашем последнем вопросе

-- i would add the name of the outer query table in the inner one
UPDATE Customers 
SET StartingBalance = StartingBalance -  (SELECT SUM(Amount) 
                                          FROM @CustomerBalance cb 
                                          WHERE Customers.Id = cb.CustomerId);

Поскольку вы используете функцию агрегирования, внутренний запрос даст вам сумму всех строк, найденных для клиента. И 0, если строка не найдена.

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