Разработка базы данных: расчет баланса счета - PullRequest
60 голосов
/ 07 декабря 2010

Как мне спроектировать базу данных для расчета баланса счета?

1) В настоящее время я рассчитываю баланс счета из таблицы транзакций. В моей таблице транзакций есть «описание» и «сумма» и т. Д.

Затем я сложил бы все значения «суммы», и это вычислило бы баланс учетной записи пользователя.


Я показал это своему другу, и он сказал, что это не очень хорошее решение,когда моя база данных будет расти, она будет замедляться ????Он сказал, что я должен создать отдельную таблицу для хранения рассчитанного баланса счета.Если это произойдет, мне придется вести две таблицы, и это рискованно, таблица баланса счета может выйти из синхронизации.

Любое предложение?

РЕДАКТИРОВАТЬ : ОПЦИЯ2: я должен добавить дополнительный столбец в мои таблицы транзакций «Баланс».теперь мне не нужно проходить через много строк данных для выполнения моих расчетов.

Пример Джон покупает кредит в размере 100 долларов США, имеет задолженность в размере 60 долларов США, затем добавляет кредит 200 долларов США..

Сумма - 60 долларов США, баланс 40 долларов США.

Сумма 200 долларов США, баланс 240 долларов США.

Ответы [ 9 ]

58 голосов
/ 07 декабря 2010

Вечная проблема, которая никогда не была элегантно решена.

Все банковские пакеты, с которыми я работал, сохраняют остаток на счету. Вычислить его на лету из истории движения немыслимо.

Правильный путь:

  • Стол для движения имеет отверстие баланс транзакции для каждого аккаунта. Тебе понадобиться это через несколько лет, когда ты нужно переместить старые движения из таблица активного движения к истории таблица.
  • У субъекта счета есть баланс поле
  • Есть триггер на движение таблица, которая обновляет аккаунт остатки по зачисленным и списанным счетам. Очевидно, у него есть обязательство контроль. Если у вас не может быть триггера, тогда должен быть уникальный модуль , который записывает движения под контролем фиксации
  • У вас есть программа «сеть безопасности», которую вы может работать в автономном режиме, который пересчитывает все весы и дисплеи (и опционально исправляет) ошибочный противовесы. Это очень полезно для тестирование.

Некоторые системы хранят все движения в виде положительных чисел и выражают кредит / дебет, инвертируя поля from / to или с флагом. Лично я предпочитаю кредитное поле, дебетовое поле и подписанную сумму, поэтому намного проще отслеживать аннулирования.

Обратите внимание, что эти методы применяются как к денежным средствам, так и к ценным бумагам.

Операции с ценными бумагами могут быть намного более хитрыми, особенно для корпоративных действий, вам потребуется учесть одну транзакцию, которая обновляет один или несколько остатков денежных средств покупателя и продавца, их остатки на обеспечительных позициях и, возможно, брокера / депозитария.

4 голосов
/ 07 декабря 2010

Вы должны хранить текущий баланс счета и постоянно обновлять его.Таблица транзакций - это просто запись того, что произошло в прошлом, и ее не следует использовать с высокой частотой просто для получения текущего баланса.Учтите, что многие запросы не просто нуждаются в балансировках, они хотят фильтровать, сортировать и группировать по ним и т. Д. Из-за потери производительности суммирования каждой транзакции, которую вы когда-либо создавали в середине сложных запросов, могут быть повреждены даже базы данных небольшого размера..

Все обновления этой пары таблиц должны выполняться в транзакции и должны обеспечивать либо синхронизацию всего (и превышение лимита учетной записи никогда не превышает своего лимита), либо откат транзакции.В качестве дополнительной меры вы можете запускать контрольные запросы, которые периодически проверяют это.

2 голосов
/ 20 мая 2016

Это дизайн базы данных, который я получил только с одной таблицей для хранения истории операций / транзакций. В настоящее время работает шармом на многих небольших проектах.

Это не заменяет определенный дизайн. Это универсальное решение, которое подходит для большинства приложений.

ID : ИНТ стандартный номер строки

operation_type : ИНТ тип операции. платить, собирать, проценты и т. д.

source_type : ИНТ откуда операция продолжается. целевая таблица или категория: пользователь, банк, поставщик и т. д.

source_id : ИНТ идентификатор источника в базе данных

target_type : ИНТ к чему применяется операция. целевая таблица или категория: пользователь, банк, поставщик и т. д.

target_id : ИНТ идентификатор цели в базе данных

сумма : десятичная дробь (подписано 19,2) значение цены положительное или отрицательное к суммированному

account_balance : десятичное число (19,2 подписано) итоговый баланс

extra_value_a : десятичный (19,2 со знаком) [это был самый универсальный вариант без использования хранения строк] Вы можете хранить дополнительное число: процентный процент, скидка, скидка и т. д.

created_at : метка времени

Для source_type и target_type лучше использовать app перечисления или таблиц.

Если вам нужен конкретный баланс, вы можете просто запросить последнюю операцию, отсортированную по убыванию предела созданного_тата до 1. Вы можете выполнить запрос по источнику, цели, типу операции и т. Д.

Для повышения производительности рекомендуется сохранять текущий баланс в требуемом целевом объекте.

2 голосов
/ 16 декабря 2011

Распространенным решением этой проблемы является поддержание (скажем) ежемесячного начального баланса в схеме моментального снимка.Расчет текущего баланса может быть сделан путем добавления транзакционных данных за месяц к ежемесячному начальному балансу.Этот подход часто используется в пакетах счетов, особенно если у вас может быть конвертация валюты и переоценка.

Если у вас есть проблемы с объемом данных, вы можете архивировать старые сальдо.может быть полезен для создания отчетов, если в вашей системе нет выделенного внешнего хранилища данных или средства управленческой отчетности.

1 голос
/ 27 декабря 2010

Конечно, вам нужно хранить текущий баланс с каждой строкой, иначе он будет слишком медленным.Чтобы упростить разработку, вы можете использовать ограничения, чтобы вам не требовались триггеры и периодические проверки целостности данных.Я описал это здесь Денормализация для обеспечения соблюдения бизнес-правил: Итоговые данные

0 голосов
/ 07 мая 2018

Мой подход заключается в том, чтобы хранить дебеты в столбце дебетов, кредит в столбце кредита и при получении данных создавать два массива: массив дебетов и кредит. Затем продолжайте добавлять выбранные данные в массив и сделайте это для python:

def real_insert(arr, index, value):
    try:
        arr[index] = value
    except IndexError:
        arr.insert(index, value)


def add_array(args=[], index=0):
    total = 0
    if index:
        for a in args[: index]:
            total += a
    else:
        for a in args:
            total += a
    return total

затем

for n in range(0, len(array), 1):
    self.store.clear()
    self.store.append([str(array[n][4])])
    real_insert(self.row_id, n, array[n][0])
    real_insert(self.debit_array, n, array[n][7])
    real_insert(self.credit_array, n, array[n][8])
    if self.category in ["Assets", "Expenses"]:
        balance = add_array(self.debit_array) - add_array(self.credit_array)
    else:
        balance = add_array(self.credit_array) - add_array(self.debit_array)
0 голосов
/ 03 июля 2012

Здесь хотелось бы предложить вам, как вы можете сохранить начальный баланс очень простым способом: -

  1. Создать триггерную функцию в таблице транзакций, которая будет вызываться только после обновленияили вставьте.

  2. Создайте столбец с именем в главной таблице имен счетов с начальным балансом.

  3. сохраните начальный баланс в массиве вначальный столбец баланса в основной таблице.

  4. вам даже не нужно использовать язык на стороне сервера, используйте этот массив хранилищ, просто вы можете использовать функции массива базы данных, такие как доступные в PostgreSQL.

  5. если вы хотите пересчитать начальный баланс в массиве, просто сгруппируйте таблицу транзакций с помощью функции массива и обновите все данные в основной таблице.

Я сделал этов PostgreSQL и работает нормально.

в течение периода времени, когда ваша таблица транзакций станет тяжелой, тогда вы можете разделить таблицу транзакций на базедаты, чтобы ускорить представление.этот подход очень прост и не требует использования каких-либо дополнительных таблиц, которые могут снизить производительность при присоединении к таблице, поскольку меньшая таблица при объединении даст вам высокую производительность.

0 голосов
/ 07 декабря 2010

Простой ответ: сделать все три.

Сохранение текущего баланса; и в каждой транзакции сохраняйте движение и снимок текущего баланса в данный момент времени. Это даст что-то дополнительные для согласования в любом аудите.

Я никогда не работал над основными банковскими системами, но я работал над системами управления инвестициями, и по моему опыту именно так это и делается.

0 голосов
/ 07 декабря 2010

Ваш друг не прав, а вы правы, и я бы посоветовал вам не менять вещи сейчас.
Если ваш БД из-за этого замедляется, и после того, как вы проверили все остальное (правильная индексация),Некоторая денормализация может оказаться полезной.
Затем вы можете поместить поле BalanceAtStartOfYear в таблицу «Счета» и суммировать только записи этого года (или любой аналогичный подход).
Но я, конечно, не рекомендовал бы такой подход заранее.

...