web-dev-qa-db-fra.com

Conception de la base de données: Calcul du solde du compte

Comment concevoir la base de données pour calculer le solde du compte?

1) Actuellement, je calcule le solde du compte à partir de la table des transactions. Dans ma table des transactions, j'ai la "description" et le "montant", etc.

J'ajouterais alors toutes les valeurs de "montant" et cela résoudrait le solde du compte de l'utilisateur.


Je l'ai montré à mon ami et il m'a dit que ce n'était pas une bonne solution, alors que ma base de données grossit, elle va ralentir ???? Il a dit que je devrais créer un tableau séparé pour stocker le solde du compte calculé. Si cela se produisait, je devrais maintenir deux tables et, en raison de ses risques, la table du solde des comptes pourrait ne pas être synchronisée.

Toute suggestion?

EDIT: OPTION 2: dois-je ajouter une colonne supplémentaire à mes tables de transaction "Balance" . maintenant, je n'ai plus besoin de parcourir plusieurs lignes de données pour effectuer mon calcul.

Exemple John achète un crédit de 100 dollars, il a une dette de 60 dollars, il ajoute ensuite un crédit de 200 dollars.

Montant 100 $, solde de 100 $.

Montant - 60 $, solde de 40 $.

Montant 200 $, solde de 240 $.

56
001

Un problème séculaire qui n'a jamais été résolu avec élégance.

Tous les paquets bancaires avec lesquels j'ai travaillé stockent le solde avec l'entité du compte. Le calculer à la volée à partir de l'histoire du mouvement est impensable.

La bonne façon est:

  • La table des mouvements a une transaction «ouverture Solde» pour chaque compte. Vous aurez besoin de Dans quelques années, lorsque vous aurez besoin de déplacer les anciens mouvements de la table des mouvements actifs vers une table d’historique
  • L'entité de compte a un champ solde
  • Il existe un déclencheur sur la table des mouvements Qui met à jour le solde du compte Pour les comptes crédités et débités. De toute évidence, il a un engagement Contrôle. Si vous ne pouvez pas avoir de déclencheur, il doit y avoir un module unique qui écrit les mouvements sous contrôle d'engagement. 
  • Vous avez un programme "filet de sécurité" que vous pouvez exécuter en mode hors connexion, ce qui recalcule tous les soldes et affiche (et corrige éventuellement) des soldes erronés Ceci est très utile pour Testing.

Certains systèmes stockent tous les mouvements sous forme de nombres positifs et expriment le crédit/débit en inversant les champs de/à ou avec un drapeau. Personnellement, je préfère un champ de crédit, un champ de débit et un montant signé, cela rend les annulations beaucoup plus faciles à suivre.

Notez que ces méthodes s'appliquent à la fois aux espèces et aux titres. 

Les transactions sur titres peuvent être beaucoup plus délicates, en particulier pour les opérations sur titres, vous devrez organiser une transaction unique mettant à jour un ou plusieurs soldes en espèces d’acheteur et de vendeur, leur solde de position sur titres et éventuellement le courtier/dépositaire.

55
smirkingman

Vous devez stocker le solde du compte courant et le maintenir à jour en tout temps. La table des transactions est juste un enregistrement de ce qui s'est passé dans le passé et ne devrait pas être utilisée à une fréquence élevée, simplement pour aller chercher le solde actuel. Considérez que beaucoup de requêtes ne veulent pas seulement des soldes, elles veulent aussi filtrer, trier et grouper, etc. La pénalité de performance consistant à additionner toutes les transactions que vous avez jamais créées au milieu de requêtes complexes paralyserait même une base de données de taille modeste. .

Toutes les mises à jour de cette paire de tables doivent figurer dans une transaction et doivent garantir que tout soit synchronisé (et que le compte ne dépasse jamais sa limite) ou que la transaction soit annulée. En guise de mesure supplémentaire, vous pouvez exécuter des requêtes d'audit qui vérifient cela périodiquement.

3
Marcelo Cantos

Une solution courante à ce problème consiste à maintenir un solde d'ouverture mensuel (par exemple) dans un schéma d'instantané. Le calcul du solde actuel peut être effectué en ajoutant des données transactionnelles pour le mois au solde d'ouverture mensuel. Cette approche est souvent utilisée dans les packages de comptes, en particulier dans les cas de conversion et de réévaluation des devises.

Si vous rencontrez des problèmes de volume de données, vous pouvez archiver les anciennes balances.

En outre, les soldes peuvent être utiles pour la création de rapports si vous ne disposez pas d'un entrepôt de données externe dédié ou d'un système de rapports de gestion sur le système.

Bien sûr, vous devez stocker votre solde actuel avec chaque ligne, sinon il est trop lent. Pour simplifier le développement, vous pouvez utiliser des contraintes, de sorte que vous n’ayez pas besoin de déclencheurs ni de contrôles périodiques de l’intégrité des données. Je l'ai décrit ici Dénormalisation pour appliquer des règles métier: Totaux cumulés

1
A-K

C'est une conception de base de données que j'ai obtenue avec une seule table pour stocker un historique des opérations/transactions. Travaille actuellement comme charme sur de nombreux petits projets.

Cela ne remplace pas une conception spécifique. Ceci est une solution générique qui pourrait convenir à la plupart des applications.

id : int identifiant de ligne standard

type_opération : int type d'opération. payer, percevoir, intérêts, etc.

type_source : int d'où se déroule l'opération . table ou catégorie cible: utilisateur, banque, fournisseur, etc.

id_source : int ID de la source dans la base de données

target_type : int à quoi l'opération est appliquée . table ou catégorie cible: utilisateur, banque, fournisseur, etc.

target_id : int id de la cible dans la base de données

montant : décimal (19,2 signé) valeur de prix positive ou négative à par

account_balance : decimal (19,2 signé) solde résultant

extra_value_a : decimal (19,2 signés) [c'était l'option la plus polyvalente sans utiliser le stockage de chaînes] vous pouvez enregistrer un numéro supplémentaire: pourcentage d'intérêt, une remise, une réduction, etc.

created_at : timestamp

Pour les types source et cible, il serait préférable d’utiliser un enum ou des tables à part.

Si vous souhaitez un solde particulier, vous pouvez simplement interroger la dernière opération triée par ordre croissant de created_at à 1. Vous pouvez interroger par source, cible, type d'opération, etc.

Pour de meilleures performances, il est recommandé de stocker le solde actuel dans l'objet cible requis.

1
Heroselohim

Mon approche consiste à stocker les débits dans une colonne de débit, un crédit dans la colonne de crédit et lors de l'extraction des données, créer deux tableaux, un tableau de débit et un tableau de crédit. Continuez ensuite à ajouter les données sélectionnées au tableau et procédez comme suit pour 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

puis 

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
kafeero

Votre ami a tort et vous avez raison, et je vous conseillerais de ne pas changer les choses maintenant.
Si votre base de données devient lente à cause de cela, et après avoir vérifié tout le reste (indexation correcte), une dénormalisation peut être utile.
Vous pouvez ensuite mettre un champ BalanceAtStartOfYear dans la table des comptes et ne résumer que les enregistrements de cette année (ou toute autre approche similaire).
Mais je ne recommanderais certainement pas cette approche dès le départ. 

0
Patrick Honorez

Voici comment vous pouvez suggérer comment vous pouvez stocker votre solde d'ouverture d'une manière très simple: -

  1. Créez une fonction de déclencheur sur la table de transaction à appeler uniquement après la mise à jour ou l'insertion.

  2. Créez une colonne dont le nom figure dans la table principale du nom de compte Solde d’ouverture.

  3. enregistrez votre solde d'ouverture dans un tableau dans la colonne "Solde d'ouverture" du tableau principal.

  4. vous n'avez même pas besoin d'utiliser le langage côté serveur pour utiliser ce tableau de magasins, vous pouvez simplement utiliser les fonctions de tableaux de bases de données telles que celles disponibles dans PostgreSQL.

  5. lorsque vous souhaitez recalculer votre solde d'ouverture dans un tableau, il vous suffit de grouper votre table de transactions avec la fonction de tableau et de mettre à jour toutes les données de la table principale.

Je l'ai fait dans PostgreSQL et fonctionne bien.

sur la période de temps pendant laquelle votre table de transaction deviendra lourde, vous pourrez alors partitionner votre table de transaction sur la base de la date pour accélérer les performances ... Cette approche est très simple et ne nécessite aucune table supplémentaire, ce qui peut ralentir performances si vous rejoignez une table car une table inférieure dans la jointure vous donnera des performances élevées.

0
Ranjeet