Programing

데이터베이스 디자인 : 계정 잔액 계산

lottogame 2020. 11. 22. 18:51
반응형

데이터베이스 디자인 : 계정 잔액 계산


계정 잔액을 계산하기 위해 데이터베이스를 어떻게 디자인합니까?

1) 현재 거래 테이블에서 계좌 잔고를 계산합니다. 거래 테이블에는 "설명"과 "금액"등이 있습니다.

그런 다음 모든 "금액"값을 더하면 사용자의 계정 잔액이 계산됩니다.


나는 이것을 내 친구에게 보여 주었고 그는 그것이 좋은 해결책이 아니라고 말했다. 내 데이터베이스가 커지면 속도가 느려질 것입니까 ???? 그는 계산 된 계정 잔액을 저장하기 위해 별도의 테이블을 만들어야한다고 말했습니다. 이렇게하면 두 개의 테이블을 유지해야하는데 계정 잔고 테이블이 동기화되지 않을 수 있습니다.

어떠한 제안?

편집 : 옵션 2 : 트랜잭션 테이블 "Balance"에 추가 열을 추가해야합니다. 이제 계산을 수행하기 위해 많은 데이터 행을 살펴볼 필요가 없습니다.

예 John은 $ 100 크레딧을 구입하고 $ 60를 빚진 다음 $ 200 크레딧을 추가합니다.

금액 $ 100, 잔액 $ 100.

금액-$ 60, 잔액 $ 40.

금액 $ 200, 잔액 $ 240.


우아하게 해결되지 않은 오래된 문제.

내가 작업 한 모든 뱅킹 패키지는 계정 엔티티에 잔액을 저장합니다. 이동 기록에서 즉석에서 계산하는 것은 생각할 수 없습니다.

올바른 방법은 다음과 같습니다.

  • 이동 테이블에는 각각의 모든 계정에 대한 '개설 잔액'트랜잭션이 있습니다. 활성 이동 테이블에서 히스토리 테이블로 이전 이동을 이동해야 할 때 몇 년 후에이 기능이 필요합니다.
  • 계정 엔터티에는 잔액 필드가 있습니다.
  • 대변 ​​및 차변 계정에 대한 계정 잔액을 업데이트하는 이동 테이블에 트리거가 있습니다. 분명히 확약 제어 기능이 있습니다. 트리거를 가질 수 없다면 커밋 제어하에 동작을 작성 하는 고유 한 모듈 이 있어야합니다.
  • 오프라인으로 실행할 수있는 '안전망'프로그램이있어 모든 잔액을 재 계산하고 잘못된 잔액을 표시 (선택적으로 수정)합니다. 이것은 테스트에 매우 유용합니다.

일부 시스템은 모든 이동을 양수로 저장하고 from / to 필드를 반전하거나 플래그를 사용하여 대변 / 차변을 표시합니다. 개인적으로 저는 신용 필드, 차변 필드 및 서명 된 금액을 선호하므로 반전을 훨씬 쉽게 수행 할 수 있습니다.

이러한 방법은 현금과 증권 모두에 적용됩니다.

증권 거래는 특히 기업 활동의 경우 훨씬 더 까다로울 수 있습니다. 하나 이상의 구매자 및 판매자 현금 잔액, 보안 포지션 잔액 및 가능하면 중개인 / 예금을 업데이트하는 단일 거래를 수용해야합니다.


현재 계정 잔액을 저장하고 항상 최신 상태로 유지해야합니다. 트랜잭션 테이블은 과거에 발생한 일에 대한 기록 일 뿐이며 현재 잔액을 가져 오기 위해 자주 사용해서는 안됩니다. 많은 쿼리가 균형을 원하는 것이 아니라 필터링, 정렬 및 그룹화하는 등의 작업을 원한다는 점을 고려하십시오. 복잡한 쿼리의 중간에 생성 한 모든 트랜잭션을 합산하는 성능 저하는 적당한 크기의 데이터베이스조차도 불구가 될 것입니다. .

이 테이블 쌍에 대한 모든 업데이트는 트랜잭션에 있어야하며 모든 항목이 동기화 상태로 유지되거나 (계정이 한도를 초과하지 않도록 초과 인출되지 않음) 트랜잭션이 롤백되도록해야합니다. 추가 조치로이를 주기적으로 확인하는 감사 쿼리를 실행할 수 있습니다.


이것은 작업 / 트랜잭션 기록을 저장하기 위해 하나의 테이블로만 얻은 데이터베이스 디자인입니다. 현재 많은 소규모 프로젝트에서 매력으로 활동하고 있습니다.

이것은 특정 디자인을 대체하지 않습니다. 이것은 대부분의 앱에 맞는 일반적인 솔루션입니다.

id : int 표준 행 ID

operation_type : int 작업 유형입니다. 지불, 수금,이자 등

source_type : int 작업이 진행되는 위치입니다. 대상 테이블 또는 범주 : 사용자, 은행, 공급자 등

source_id : int 데이터베이스에있는 소스의 id

target_type : int 작업이 적용됩니다. 대상 테이블 또는 범주 : 사용자, 은행, 공급자 등

target_id : int 데이터베이스의 대상 ID

amount : decimal (19,2 signed) 가격 값을 합산하여 양수 또는 음수

account_balance : decimal (19,2 signed) 결과 잔액

extra_value_a : decimal (19,2 signed) [문자열 저장을 사용하지 않는 가장 다재다능한 옵션] 이자율, 할인, 할인 등 추가 숫자를 저장할 수 있습니다.

created_at : 타임 스탬프

source_type 및 target_type의 경우 enum 또는 tables appart를 사용하는 것이 좋습니다.

특정 잔액을 원하면 created_at 내림차순으로 정렬 된 마지막 작업을 1로 쿼리 할 수 ​​있습니다. 소스, 대상, operation_type 등으로 쿼리 할 수 ​​있습니다.

더 나은 성능을 위해 필요한 대상 개체에 현재 잔액을 저장하는 것이 좋습니다.


이 문제에 대한 일반적인 해결책은 스냅 샷 스키마에서 월간 개시 잔액을 유지하는 것입니다. 현재 잔액 계산은 월간 시작 잔액에 해당 월의 거래 데이터를 추가하여 수행 할 수 있습니다. 이 접근 방식은 특히 통화 변환 및 재평가가있을 수있는 계정 패키지에서 자주 사용됩니다.

데이터 볼륨에 문제가있는 경우 이전 잔액을 보관할 수 있습니다.

또한 시스템에 전용 외부 데이터웨어 하우스 또는 관리보고 기능이없는 경우 잔액을보고하는 데 유용 할 수 있습니다.


물론 현재 잔액을 각 행에 저장해야합니다. 그렇지 않으면 너무 느립니다. 개발을 단순화하기 위해 제약 조건을 사용할 수 있으므로 트리거와 데이터 무결성에 대한주기적인 검사가 필요하지 않습니다. 난 여기가 설명 비즈니스 규칙을 적용 할 비정규 : 실행 합계


당신의 친구는 틀렸고 당신은 옳습니다. 지금은 바꾸지 말라고 조언하겠습니다.
이로 인해 db가 느려지고 나머지 (적절한 인덱싱)를 모두 확인한 후 일부 비정규 화를 사용할 수 있습니다.
그런 다음 Accounts 테이블에 BalanceAtStartOfYear 필드를 배치하고 올해 레코드 (또는 유사한 접근 방식) 만 요약 할 수 있습니다.
하지만이 접근 방식을 미리 권장하지는 않습니다.


Here is would like to suggest you how can you store your opening balance with a very simple way:-

  1. Create a trigger function on the transaction table to be called only after update or insert.

  2. Create a column having name in the master table of account naming Opening Balance.

  3. save your opening balance in array in the opening balance column in master table.

  4. you even not need to use server side language use this store array simply you can use database array functions like available in PostgreSQL.

  5. when you want to recalculate you opening balance in array just group your transaction table with array function and update the whole data in the master table.

I have done this in PostgreSQL and working fine.

over the period of time when your transaction table will become heavy then you can partition for your transaction table on the base of date to speed up the performance. this approach is very easy and need not to use any extra table which can slow performance if joining table because lesser table in the joining will give you high performance.


My approach is to store the debits in a debit column, credit in the credit column and when fetching the data create two arrays, debit and credit array. Then keep appending the selected data to the array and do this for 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

then

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)

Simple answer: Do all three.

Store the current balance; and in each transaction store the movement and a snapshot of the current balance at that point in time. This would give something extra to reconcile in any audit.

I've never worked on core banking systems, but I have worked on investment management systems, and in my experience this is how It's done.

참고URL : https://stackoverflow.com/questions/4373968/database-design-calculating-the-account-balance

반응형