Consulenza per la progettazione di database


8

Sto progettando un database per il nostro team di vendita da utilizzare come strumento di quotazione rapida dei lavori. Vorrei un feedback su un aspetto particolare del design.

Un preventivo viene sostanzialmente creato selezionando un elenco di "assiemi" predefiniti ciascuno con un prezzo concordato. Una vista semplificata del modulo principale è simile alla seguente:

                                                  +------------ --- ---+
                                                  | Assembly options   |
+------------+------------+----------+------------+---+---+---+ --- +--+
| assembly  | unit cost  | quantity | total cost | 1 | 2 | 3 |     |50|
+------------+------------+----------+------------+---+---+---+ --- +--+
| VSD55      | £10'000    | 2        | £25'500    | 1 | 1 |   |     |  | 
| RDOL2.2    | £2'000     | 1        |  £1'500    |   | 1 |   |     |  | 
| DOL5.0     | £1'000     | 1        |  £1'200    |   |   | 1 |     |  | 
+------------+------------+----------+------------+---+---+---+ --- +--+

L'utente seleziona un assieme predefinito, inserisce la quantità e seleziona tutte le "opzioni" richieste. Ogni assieme ha potenzialmente fino a 50 opzioni disponibili. Un'opzione è anche un assieme predefinito (sottoassieme) con il suo prezzo. Il "costo totale" per ogni riga viene calcolato come (costo dell'assemblaggio principale * quantità) + costo di eventuali opzioni.

Quando l'utente sposta il cursore in una casella di opzione, vengono resi noti il ​​nome e il prezzo di tale opzione.

Ora è qui che diventa complicato. Ogni assieme ha il proprio elenco di opzioni disponibili. cioè l'opzione 1 per un 'VSD55' rappresenta un sottoinsieme diverso rispetto all'opzione 1 per un DOL5.0.

Per quanto riguarda gli assemblaggi, ecco le tabelle semplificate che sto usando:

+-----------------+    +------------------------+    +-----------------------------+
| assembly        |    | assembly_option        |    | assembly_option_link        |
+-----------------+    +------------------------+    +-----------------------------+
| assembly_id (PK)|    | assembly_option_id (PK)|    | assembly_option_link_id (PK)|
| assembly_name   |    | assembly_option_name   |    | assembly_id (FK)            |
| unit_cost       |    | option_number          |    | assembly_option_id (FK)     |
+-----------------+    | unit_cost              |    +-----------------------------+
                       +------------------------+

La tabella 'assembly_option_link' definisce sostanzialmente quali opzioni sono disponibili per ciascun assembly.

Ora per le tabelle 'quote':

 +-----------------+    +------------------------+    
 | quote           |    | quote_assembly         |    
 +-----------------+    +------------------------+    
 | quote_id (PK)   |    | quote_assembly_id (PK) |
 | quote_name      |    | assembly_id (FK)       |
 +-----------------+    | quantity               |
                        +------------------------+    

Ora la parte difficile è come memorizzare tutte le opzioni selezionate. Devo espandere la tabella 'quote_assembly' con tutti i 50 campi opzione anche se questo infrange le regole di normalizzazione. Un assieme non verrà mai selezionato con tutte e 50 le opzioni, quindi anche questo sembra molto inefficiente. Tra i lati positivi, questa soluzione consente al modulo di immissione dell'utente di mappare direttamente alla tabella, semplificando la codifica.

La soluzione 'normalizzata' penso che sarebbe quella di creare un'altra tabella come questa:

+------------------------------+
| quote_assembly_option        |
+------------------------------+
| quote_assembly_option_id (PK)|
| quote_assembly_id (FK)       |
| assembly_option_id (FK)      |
| quantity                     |
+------------------------------+

Questa soluzione significa che sono memorizzate solo le opzioni selezionate. Inoltre, anziché memorizzare il numero_opzione, posso archiviare l'attuale 'assembly_option_id'. Ciò semplifica quindi il calcolo del costo totale dell'offerta poiché non è necessario convertire tra 'option_number' e 'assembly_option_id' per cercare il costo dell'opzione di assemblaggio. Lo svantaggio principale di questa soluzione è che non si adatta bene al modulo di iscrizione dell'utente. Penso che dovrò applicare un codice di fantasia per interfacciare il modulo con le tabelle.

Qualcuno può offrire qualche consiglio di progettazione qui per favore? Spero di essermi spiegato abbastanza bene.

ULTERIORI INFORMAZIONI
Questo è anche un rapporto di offerta dettagliato che espande le opzioni selezionate come elementi pubblicitari separati nell'assieme principale. Per esempio:

+---------------------------------+------------+----------+------------+
| assembly                        | unit cost  | quantity | total cost |
+---------------------------------+------------+----------+------------+
| VSD55                           | £10'000    | 2        |   £20'000  |
|   - Seal leak protection        | £ 5'000    | 1        |   £ 5'000  |   <-option 1
|   - Motor over temp protection  | £   500    | 1        |   £   500  |   <-option 2
+---------------------------------+------------+----------+------------+
|                                 |            |          |   £25'500  |
+---------------------------------+------------+----------+------------+

Risposte:


3
                                                  +------------ --- ---+
                                                  | Assembly options   |
+------------+------------+----------+------------+---+---+---+ --- +--+
| assembly  | unit cost  | quantity | total cost | 1 | 2 | 3 |     |50|
+------------+------------+----------+------------+---+---+---+ --- +--+
| VSD55      | £10'000    | 2        | £20'000    | 1 | 1 |   |     |  | 

Se qualcuno mi consegnasse quella citazione, la mia prima domanda sarebbe "Qual è l'opzione 1 per il VSD55?" La risposta sarebbe "Non lo so". Quelle informazioni non sono sulla citazione. Nell'improbabile eventualità che una persona abbia avuto una seconda domanda, quella domanda sarebbe "Quanto costa?" Ancora una volta, la risposta sarebbe "Non lo so". Un silenzio molto inquietante sarebbe seguito immediatamente, durante il quale la persona che mi ha consegnato la citazione avrebbe immaginato quanto potrebbe essere meglio essere investito da un treno.

Le opzioni devono essere elementi pubblicitari nel preventivo, insieme al prezzo unitario, alla quantità e al prezzo totale. Le opzioni devono essere nominate, non numerate. Dovrebbero apparire direttamente anche sotto la loro assemblea dei genitori, non sparsi per l'inferno e metà della Georgia.

Se vuoi un colpo ai miei soldi, è meglio che chiarisca cosa dovrei ottenere per i miei soldi.

Non c'è nulla (molto) sbagliato con 50 caselle di controllo in un modulo di interfaccia utente. Ciò semplifica la scelta delle opzioni. Ma il codice UI dovrebbe leggere le caselle di controllo e inserire le informazioni giuste nelle tabelle normalizzate.


Sembra che tu stia offrendo consigli sui processi aziendali, che non sono disponibili per l'opzione, che David sta cercando di incapsulare nel modo migliore che conosce per il progetto che gli è stato assegnato. ~ Ora, sono d'accordo che un dba dovrebbe influenzare il design dove sono in grado, ma a volte non può essere aiutato. Ricorda anche che questo è uno strumento interno (vedi la prima riga)
jcolebrand

1
Commenti abbastanza equi, mi ha fatto ridere! Naturalmente abbiamo un rapporto di quotazione che fa esattamente quello che stai suggerendo. Da allora ho aggiunto questo dettaglio alla domanda originale per evitare ulteriori discussioni fuori tema;)
David,

3

L'ultima opzione che dai è il modo in cui vorrei andare con esso. E restituisce due tabelle raggruppate, una per la "riga principale" e una per le righe raccolte "esiste" per le 50 colonne. Supponendo che sia possibile mappare l'opzione sull'ID colonna appropriato abbastanza facilmente (sembra che tu possa farlo senza troppi tempi difficili).

Sarebbe abbastanza facile per l'iterazione, assumendo un linguaggio come C #, dove hai LINQ disponibile, ecc. Questi sono abbastanza facili da fare, anche se comportano un po 'di loop (è il codice dell'interfaccia utente, deve essere fatto ad un certo punto ). Oppure potresti fare un perno nel database prima di tornare ... sarebbe più veloce. Ma manterrà comunque la complessità.

Ma il tuo design mi suona bene.


0

L'aggiunta del tuo tavolo extra mi sembra abbastanza discreta.

Quando ho affrontato un problema simile da parte mia, ho esplorato la memorizzazione di un albero nella tabella order_lines. Nel caso in cui hai considerato qualcosa di simile, ho avuto:

  • un parent_idcampo aggiuntivo per order_linese una chiave esterna in modo che (parent_id, product_id)possa fare riferimento(order_line_id, product_id)

  • Un vincolo di controllo in modo da rendere disponibile un'opzione implicherebbe un genitore (nel mio caso check((option_id is not null) = (parent_id is not null))).

In altre parole, lascio che l'interfaccia utente abbia una parola su come devono essere archiviate le cose:

+---------------------------------+------------+----------+------------+
| assembly                        | unit cost  | quantity | total cost |
+---------------------------------+------------+----------+------------+
| VSD55                           | £10'000    | 2        |   £20'000  |
|   - Seal leak protection        | £ 5'000    | 1        |   £ 5'000  |
|   - Motor over temp protection  | £   500    | 1        |   £   500  |
+---------------------------------+------------+----------+------------+

Dal punto di vista della codifica dell'interfaccia utente sembrava giusto. Ma presto si è sentito male dal punto di vista delle regole di business, in quanto ha introdotto una varietà di problemi lungo la strada. (Ho dovuto affrontare tutti i tipi di casi speciali con i trigger.)

Quindi non raccomandato ... Nella misura in cui ho riscontrato casi simili, il tuo approccio attuale sarà meno soggetto a problemi lungo la strada.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.