Ich entwerfe eine Datenbank, die unser Verkaufsteam als schnelles Tool für die Angebotserstellung verwenden kann. Ich hätte gerne ein Feedback zu einem bestimmten Aspekt des Designs.
Ein Angebot wird im Wesentlichen durch Auswahl einer Liste vordefinierter "Baugruppen" mit jeweils einem vereinbarten Preis erstellt. Eine vereinfachte Ansicht des Hauptformulars sieht folgendermaßen aus:
+------------ --- ---+
| 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 | | |
+------------+------------+----------+------------+---+---+---+ --- +--+
Der Benutzer wählt eine vordefinierte Baugruppe aus, gibt die Menge ein und wählt alle erforderlichen Optionen aus. Für jede Baugruppe stehen möglicherweise bis zu 50 Optionen zur Verfügung. Eine Option ist auch eine vordefinierte Baugruppe (Unterbaugruppe) mit eigenem Preis. Die 'Gesamtkosten' für jede Linie werden berechnet als (Hauptmontagekosten * Menge) + Kosten aller Optionen.
Wenn der Benutzer seinen Cursor in ein Optionsfeld bewegt, werden ihm Name und Preis dieser Option bekannt gegeben.
Hier wird es kompliziert. Jede Baugruppe verfügt über eine eigene Liste verfügbarer Optionen. dh Option 1 für einen 'VSD55' stellt eine andere Unterbaugruppe dar als Option 1 für einen DOL5.0.
Was die Baugruppen betrifft, sind hier die vereinfachten Tabellen, die ich verwende:
+-----------------+ +------------------------+ +-----------------------------+
| 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 | +-----------------------------+
+------------------------+
Die Tabelle 'assembly_option_link' definiert grundsätzlich, welche Optionen für jede Assembly verfügbar sind.
Nun zu den 'Zitat'-Tabellen:
+-----------------+ +------------------------+
| quote | | quote_assembly |
+-----------------+ +------------------------+
| quote_id (PK) | | quote_assembly_id (PK) |
| quote_name | | assembly_id (FK) |
+-----------------+ | quantity |
+------------------------+
Der schwierige Teil ist nun, wie ausgewählte Optionen gespeichert werden. Sollte ich die Tabelle 'quote_assembly' mit allen 50 Optionsfeldern erweitern, obwohl dies gegen die Normalisierungsregeln verstößt? Eine Baugruppe wird niemals mit allen 50 Optionen ausgewählt, daher scheint dies auch sehr ineffizient zu sein. Auf der positiven Seite ermöglicht diese Lösung, dass das Benutzereingabeformular direkt der Tabelle zugeordnet wird, was die Codierung vereinfacht.
Die 'normalisierte' Lösung wäre meiner Meinung nach, eine andere Tabelle wie diese zu erstellen:
+------------------------------+
| quote_assembly_option |
+------------------------------+
| quote_assembly_option_id (PK)|
| quote_assembly_id (FK) |
| assembly_option_id (FK) |
| quantity |
+------------------------------+
Diese Lösung bedeutet, dass nur ausgewählte Optionen gespeichert werden. Anstatt die Option_Nummer zu speichern, kann ich auch die tatsächliche 'Assembly_Option_ID' speichern. Dies vereinfacht dann die Berechnung der Gesamtkosten für das Angebot, da ich nicht zwischen 'option_number' und 'Assembly_option_id' konvertieren muss, um die Kosten für die Assembly-Option nachzuschlagen. Der Hauptnachteil dieser Lösung ist jedoch, dass sie nicht gut zum Benutzereingabeformular passt. Ich denke, ich muss eine ausgefallene Codierung anwenden, um das Formular mit den Tabellen zu verbinden.
Kann hier bitte jemand eine Designberatung anbieten? Ich hoffe ich habe mich gut genug erklärt.
MEHR INFO Dies
ist auch ein detaillierter Angebotsbericht, der alle ausgewählten Optionen als separate Positionen unter der Hauptbaugruppe erweitert. Zum Beispiel:
+---------------------------------+------------+----------+------------+
| 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 |
+---------------------------------+------------+----------+------------+
Die letzte Option, die Sie geben, ist die Art und Weise, wie ich damit umgehen würde. Und geben Sie zwei gruppierte Tabellen zurück, eine für die "Hauptzeile" und eine für die gesammelten "Existiert" -Zeilen für die 50 Spalten. Angenommen, Sie können die Option einfach genug der entsprechenden Spalten-ID zuordnen (es sieht so aus, als könnten Sie dies ohne allzu große Schwierigkeiten tun).
Das wäre für die Iteration einfach genug, wenn man eine Sprache wie C # voraussetzt, in der LINQ verfügbar ist usw. Diese sind einfach genug, auch wenn sie ein wenig schleifen (es ist UI-Code, es muss irgendwann gemacht werden ). Oder Sie könnten einen Pivot in der Datenbank machen, bevor Sie zurückkehren ... das wäre schneller. Aber es wird immer noch die Komplexität beibehalten.
Aber dein Design klingt für mich.
quelle
Das Hinzufügen Ihres zusätzlichen Tisches scheint mir auch ziemlich vernünftig zu sein.
Als ich mich mit einem ähnlichen Problem befasste, untersuchte ich das Speichern eines Baums in der Tabelle order_lines. Falls Sie etwas Ähnliches in Betracht gezogen haben, hatte ich:
ein zusätzliches
parent_id
Feld fürorder_lines
und ein Fremdschlüssel, auf(parent_id, product_id)
den verwiesen wird(order_line_id, product_id)
Eine Überprüfungsbeschränkung, um eine Option zu erhalten, würde einen Elternteil implizieren (in meinem Fall
check((option_id is not null) = (parent_id is not null))
).Mit anderen Worten, ich habe der Benutzeroberfläche ein Wort darüber gegeben, wie Dinge gespeichert werden sollen:
Vom Standpunkt der UI-Codierung aus schien es richtig zu sein. Unter dem Gesichtspunkt der Geschäftsregeln fühlte es sich jedoch schnell falsch an, da es später eine Reihe von Problemen aufwirft. (Ich musste mich mit allen möglichen Sonderfällen bei Auslösern befassen.)
Also nicht zu empfehlen ... Soweit ich ähnliche Fälle erlebt habe, wird Ihr derzeitiger Ansatz später weniger problematisch sein.
quelle