Plusieurs tables sur une seule ligne dans une database relationnelle

Considérons que nous avons une database qui a une table, qui est un logging d'une vente. Vous vendez à la fois des produits et des services, de sorte que vous disposez également d'une table de produits et de services.

Chaque vente peut être un produit ou un service, ce qui laisse les options pour concevoir la database comme suit:

  1. Ajouter des colonnes pour chaque type, à savoir. ajoutez Service_id et Product_id à Invoice_Row, dont les deux colonnes sont nullables. Si elles sont toutes les deux nulles, il s'agit d'une charge ad hoc ne se rapportant à rien, mais si l'une d'entre elles est satisfaite, alors il s'agit d'une ligne relative à ce type.

  2. Ajoutez un étrange système basé sur une string / id, par exemple: Type_table, Type_id. Ce serait respectivement une string / varchar et un entier, le premier contiendrait par exemple 'Service', et le second l'id dans la table Service. C'est évidemment un couplage lâche et horrible, mais c'est une façon de le résoudre tant que vous n'accédez au DB qu'à partir du code, en tant que tel.

  3. Exclure le concept de «quelque chose qui est facturable» pour de nouvelles tables, dont le produit et le service sont maintenant une abstraction, et sur la table Invoice_Row, vous lieriez à quelque chose comme ChargeableEntity_id. Cependant, la table ChargeableEntity ici serait essentiellement redondante car elle aurait aussi besoin d'un lien vers une table "backend" abstraite, ce qui nous ramène au même problème.

De quelle façon choisiriez-vous, ou quelles sont les autres alternatives à la résolution de ce problème?

Ce que vous requestz essentiellement, c'est comment réaliser le polymorphism dans une database relationnelle. Il existe de nombreuses approches (comme vous le démontrez vous-même) à ce problème. Une solution consiste à utiliser l'inheritance "table par class". Dans cette configuration, il y aura une table parente (semblable à votre "élément taxable") qui contient un identifiant unique et les champs communs aux produits et aux services. Il y aura deux tables, produits et biens pour enfants: Chacun contiendra l'identifiant unique de cette entité et les champs qui lui sont propres.

Un avantage de cette approche par rapport aux autres est que vous ne vous retrouvez pas avec une table avec beaucoup de colonnes nullables qui devient essentiellement un dépotoir pour décrire n'importe quoi ("sans schéma").

Un inconvénient est que votre hiérarchie d'inheritance se développe, le nombre de jointures nécessaires pour saisir toutes datatables d'une entité augmente également.

Je crois que cela dépend des cas d'utilisation.

  1. Vous pouvez placer les colonnes communes dans une table et placer des colonnes spécifiques au produit et au service dans ses propres tables.Voici l'accord est que vous devez joindre des choses.

  2. Sinon, si vous maintenez deux tables distinctes, une pour le produit et une autre pour la vente. Vous utilisez la logique d'application pour déterminer dans quelle table insert. Et get toutes les ventes signifiera essentiellement, l'union de tous les produits et d'get toutes les ventes.

J'irais personnellement à l'approche 2 pour éviter les jointures et les insert dans deux arrays chaque fois qu'une vente est faite.