Va bene avere una relazione molti-a-molti in cui una delle tabelle coinvolte è già una tabella di giunzione?

3

Durante la pianificazione del nostro database, abbiamo finito con una configurazione come questa:

Abbiamo Company , Product e Person .

Esiste una relazione molti-a-molti tra Company e Product , attraverso una tabella di giunzione Company_Product , perché una determinata azienda può produrre più di un prodotto (come "auto" e "bicicletta") ma anche un determinato prodotto, come "car", può essere prodotto da più aziende. Nella tabella di giunzione Company_Product esiste un campo "prezzo" in più, che è il prezzo in cui la data società vende il prodotto dato.

Esiste un'altra relazione molti-a-molti tra Company_Product e Person , attraverso una tabella di giunzione Company_Product_Person . Sì, è una relazione molti-a-molti che coinvolge una entità che è già una tabella di giunzione. Ciò è dovuto al fatto che una Persona può possedere più prodotti, come un'auto dalla società1 e una bicicletta dalla società2, e a sua volta lo stesso company_product può essere posseduto da più di una persona, poiché ad esempio sia la persona1 che la persona2 avrebbero potuto acquistare una macchina da company1. Nella tabella di giunzione Company_Product_Person è presente un campo extra "pensieri" che contiene i pensieri della persona al momento dell'acquisto di company_product.

Questo è comunemente accettabile o è un segno che qualcosa non va? Se è strano, quale sarebbe una soluzione migliore?

Ho riscontrato alcuni problemi con questo ( come questo ), quindi mi chiedevo, forse la mia configurazione del database è sbagliata per cominciare.

    
posta Pedro A 09.02.2018 - 20:49
fonte

3 risposte

4

Nel fare la progettazione logica del tuo database, non dovresti pensare in termini di "tabelle di giunzione", ma in termini di relazioni.

La tua prima "tabella di giunzione" sembra corrispondere alla relazione " La società vende Prodotto per Prezzo ". La tua seconda "tabella di congiunzione" sembra corrispondere alla relazione " Persona proprietaria Prodotto prodotto da Azienda ".

Anche se dipenderebbe dal contesto completo, probabilmente modellerei la seconda relazione come una tabella con chiavi esterne nelle tabelle Company , Product e Person e senza connessione con l'altro "junction tavolo". Ciò solleva il rischio che io possa affermare che una persona è proprietaria di un prodotto che non è mai stato fabbricato da un'azienda, ma consente anche di eliminare una riga dalla tabella "prodotti di vendita" senza perdere tutte le informazioni sulla proprietà di chi è proprietario del prodotto da quella compagnia Forse questo non è un problema per te, nel qual caso questo non è un motivo per non strutturare le tabelle nel modo che suggerisci, e il rischio che ho menzionato prima è un motivo per strutturare le tabelle nel modo in cui suggerisci.

Più in generale, ciò che consiglierei (oltre a pensare in termini relazionali piuttosto che in termini di "tabelle" e "tabelle di giunzione") è considerare cosa succede quando le cose cambiano. Ad esempio, supponiamo di voler calcolare quanto una persona ha speso per vari prodotti. Se i prezzi possono cambiare, non è possibile farlo con la rappresentazione suggerita (né il mio suggerimento senza aggiungere ulteriori informazioni), poiché la persona potrebbe aver acquistato il prodotto in un momento in cui il prezzo era diverso. Le tecniche di database temporali possono gestire queste situazioni in generale, ma farlo completamente spesso è eccessivo. Tuttavia, consiglio di consultare i database temporali in quanto tendono a modellare la situazione in modo più accurato. Da lì puoi considerare quali dati (se ce ne sono) non sono importanti e quindi puoi perdere. (I database temporali di solito sono "solo inserti".) Sospetto che se si tiene conto di come i dati possono cambiare nel tempo, si vorrà uno schema diverso dal tuo suggerimento originale e dal mio suggerimento.

    
risposta data 10.02.2018 - 08:44
fonte
1

Supponiamo di avere una giunzione tra 2 tabelle ( AB ), quindi tra loro e ancora un'altra tabella ( ABC ).

Possiamo dire che AB può essere una relazione molto più piccola, quindi può essere conservata nella RAM, mentre ABC è enorme e non si adatta. Quindi le query che toccano AB sarebbero più veloci delle query a ABC . Un indice separato solo su A e B su ABC sarebbe ancora molto più grande di un indice su coppie AB uniche.

OTOH non farei che ABC dipenda da AB per un FK; invece lo farei dipendere da A , B e C direttamente.

    
risposta data 09.02.2018 - 21:01
fonte
0

OP qui.

Dopo aver letto le risposte fornite e approfondito la ricerca e il pensiero sull'argomento, ho concluso che non c'è nulla di tecnicamente sbagliato nella mia configurazione per sé . Tuttavia, poiché mi trovavo di fronte a un problema pratico, ho trovato una soluzione che consisteva nel rielaborare un po 'le relazioni nel mio schema. Non so se le mie difficoltà fossero specifiche dell'ORM JavaScript che stavo usando (ovvero sequelize ) o che esisterebbe anche in altri ORM , ma a prescindere, ho trovato una configurazione diversa che ha anche senso ed evita questo problema.

Così, ho deciso di pubblicare anche qui la mia risposta, in modo che se qualcuno incappa in una situazione simile, forse modificare lo schema come ho fatto aiuterà (anche se lo schema originale non è tecnicamente sbagliato).

Citando la mia risposta alla mia domanda collegata su SO :

Analyzing the old approach

First of all, both junction tables given in my question were more than "just" junction tables. They weren't simply a tool to define which elements were related to which elements, but they were something more:

  • They also had extra information (the fields "price" and "thoughts", respectively);

  • The first one, Company_Product, also had relationships with other tables itself.

This is not technically wrong, strictly speaking, but there is a more natural way to structure the database to represent the same things. And better, with this new approach, making the query I want becomes very simple.

Solution: new approach

The solution rises when we see that we are modeling items that can be purchased and the purchases themselves. Instead of keeping this information "disguised" inside the junction table of a many-to-many relationship, we shall have them as explicit entities in our scheme, with their own tables.

So, first, to clarify, let's rename our models:

  • Company stays Company
  • Product becomes ProductType
  • Company_Product becomes Product
  • Person stays Person
  • Company_Product_Person becomes Purchase

And then we see that:

  • A Product has one Company and one ProductType. Conversely, the same Company can be related to multiple Product and the same ProductType can be related to multiple Product.
  • A Purchase has one Product and one Person. Conversely, the same Product can be related to multiple Purchase and the same Product can be related to multiple Person.

Note that there are no many-to-many relationships anymore.

[...]

Instead of using junction tables that were more than simple junction tables, we got rid of the many-to-many relationships and "promoted" the junction tables to full-fledged entities of our scheme. In fact, the tables are the same; the changes were only in the relations and in the way to look at them.

    
risposta data 16.02.2018 - 14:02
fonte