Realisierung einer Stücklisten

Tinitus

Benutzer
Beiträge
6
Hallo,

ich programiere in C# eine Waren-Wirtschafts-System das mit einer MySQL-Datenbank arbeitet.
Es soll Atrikel geben. Ein Artikel kann eine einzelne Position sein, oder eine Baugruppe die sich aus mehreren Einzelpositionen zusammensetzt.
Ich habe also folgende Tabellen erstellt:

ER-Model.JPG

Da ich nur ein happigs Semester Datenbank-Kontakt hatte, bin ich mir unsicher ob das mit den Primär- und Fremdschlüsseln so seine Richtigkeit hat.
Der Knoten in meinem Hirn entsteht an der Stelle wo eine Baugruppe(Stückliste) selber ein StockContent ist. Im Lager(StockContents) sind alle Bauteile und Baugruppen enthalten. Ein Einzelteil hätte als Kategorie "Bauteil" und eine Stückliste "Baugruppe" zugeordnet.
 

Anhänge

  • ER-Model.JPG
    ER-Model.JPG
    42,4 KB · Aufrufe: 38
Zuletzt bearbeitet:
Werbung:
Hallo,

ich programiere in C# eine Waren-Wirtschafts-System das mit einer MySQL-Datenbank arbeitet.
Es soll Atrikel geben. Ein Artikel kann eine einzelne Position sein, oder eine Baugruppe die sich aus mehreren Einzelpositionen zusammensetzt.

Was genau ist denn jetzt das Problem:

Ich kann mit solchen Bildern nicht viel anfangen, eher mit der Definition der Tabellen.



Dein 2. Satz da ober erinnert mich aber einen Vortrag von Peter Eisentraut, den es auch Online gibt: http://de.slideshare.net/petereisentraut/spa-mit-postgresql?nomobile=true , da ist auch eine Stückliste für ein Auto, welches auf rekursiven Abfragen aufbaut bzw. diese erklärt.
Also, es gibt Einzelteile wie Schrauben und Kolben, es gibt den Motor, welcher als Baugruppe u.a. aus Schreiben und Kolben besteht, und es gibt das Auto, was einen Motor und weitere Schrauben hat. Sowas läßt sich natürlich sehr schön rekursiv darstellen - was MySQL allerdings so nicht kann.
 
Hier der Code:
Code:
CREATE TABLE [dbo].[StockContents] (
  [Content_Id]  VARCHAR (8)  NOT NULL,
  [Image_Id]  INT  NULL,
  [Department_Id] VARCHAR (2)  NOT NULL,
  [Category_Id]  VARCHAR (2)  NOT NULL,
  [Name]  VARCHAR (50)  NOT NULL,
  [Description]  VARCHAR (MAX) NULL,
  [Version]  INT  CONSTRAINT [DF_Artikel_Version] DEFAULT ((0)) NOT NULL,
  CONSTRAINT [PK_Artikel] PRIMARY KEY CLUSTERED ([Content_Id] ASC),
  CONSTRAINT [FK_StockContents_Departments] FOREIGN KEY ([Department_Id]) REFERENCES [dbo].[Departments] ([Department_Id]),
  CONSTRAINT [FK_StockContents_Categorys] FOREIGN KEY ([Category_Id]) REFERENCES [dbo].[Categorys] ([Category_Id])
);
CREATE TABLE [dbo].[Usage] (
  [Content_Id]  VARCHAR (8)  NOT NULL,
  [Assembly_Id] VARCHAR (8)  NOT NULL,
  [Count]  INT  CONSTRAINT [DF_Verwendung_Anzahl] DEFAULT ((0)) NOT NULL,
  [Position]  INT  NULL,
  [Partname]  VARCHAR (MAX) NULL,
  CONSTRAINT [FK_Usage_StockContents] FOREIGN KEY ([Content_Id]) REFERENCES [dbo].[StockContents] ([Content_Id])
);

Mit deinem Link konnte ich leider nicht viel anfangen, wie gesagt bin ich was Datenbanken angeht ein Laie.
Ich glaube allerdings, das mein Ansatz, aus einer Tabelle mit zwei verschiedenen Spalten auf eine Spalte einer anderen Tabelle zu referenzieren, nicht klappt.
Der Gedanke war ja, das ein Artikel ein Einzelstück oder eine Baugruppe sein kann. Dazu muss ich ja wissen welche Einzelstücke(Zeilen in StockContents) einer Baugruppe(eine Zeile in, ebenfalls, StockContents) zugewiesen sind.

Kann man das so umsetzen, oder wäre eine weitere Tabelle "Assemblys" ratsam? Damit könnte man von der Tabelle "Usage" auf eine Zeile in "Assemblys" und eine Zeile in "StockContenst" zeigen und von "StockContents" wiederum auf eine Zeile in "Assemblys", da diese ja auch im Lager liegen können. Um eine Baugruppe auszuwählen würde man zwei Schritte benötigen:
  1. alle Zeilen aus "Usage" laden, in denen die Assembly_Id der gewünschten Baugruppe entspricht.
  2. über alle Resultate iterieren und sich die Zeile aus "StockContents" holen, in der die Content_Id der des Iterators entspricht.
Was mich von dieser Variante abhält sind die vielen Abfragen durch die Iteration des Anwendungsprogrammes und die Tatsacht, dass ich zwei Tabellen habe (StockContents und Assemblys), die die gleiche Bedeutung haben: Elemente im Lager.
 

Das ist aber eher M$SQL undnicht MySQL, oder?

Mit deinem Link konnte ich leider nicht viel anfangen, wie gesagt bin ich was Datenbanken angeht ein Laie.
Ich glaube allerdings, das mein Ansatz, aus einer Tabelle mit zwei verschiedenen Spalten auf eine Spalte einer anderen Tabelle zu referenzieren, nicht klappt.
Hä?

Der Gedanke war ja, das ein Artikel ein Einzelstück oder eine Baugruppe sein kann. Dazu muss ich ja wissen welche Einzelstücke(Zeilen in StockContents) einer Baugruppe(eine Zeile in, ebenfalls, StockContents) zugewiesen sind.

Kann man das so umsetzen, oder wäre eine weitere Tabelle "Assemblys" ratsam? Damit könnte man von der Tabelle "Usage" auf eine Zeile in "Assemblys" und eine Zeile in "StockContenst" zeigen und von "StockContents" wiederum auf eine Zeile in "Assemblys", da diese ja auch im Lager liegen können. Um eine Baugruppe auszuwählen würde man zwei Schritte benötigen:
  1. alle Zeilen aus "Usage" laden, in denen die Assembly_Id der gewünschten Baugruppe entspricht.
  2. über alle Resultate iterieren und sich die Zeile aus "StockContents" holen, in der die Content_Id der des Iterators entspricht.
Was mich von dieser Variante abhält sind die vielen Abfragen durch die Iteration des Anwendungsprogrammes und die Tatsacht, dass ich zwei Tabellen habe (StockContents und Assemblys), die die gleiche Bedeutung haben: Elemente im Lager.

Prüf doch erst mal, was Du für eine DB hast. Ich bin mir jetzt nicht sicher, aber ich könnte mir vorstellen, daß M$SQL auch rekursive Abfragen kann. Dann könntest Du das Beispiel von Peter E. (Folie 12, 2. Beispiel für rekursive Abfragen) faktisch 1:1 übernehmen.
 
Ohne mich jetzt wirklich mit dem Thema Stücklisten oder dem Vortrag zu befassen würde ich sagen es geht mit MSSQL aber in dem ERD fehlt irgendwie was. Usage muss doch sowas wie ne Zwischentabelle zwischen dem Teil und seinen Komponenten sein. Wenn jetzt eine Komponente weitere Komponenten haben kann gibt es nur eine Tablle für Teile bzw. Komponenten und Usage ist die Zwischentabelle einer n:m Beziehung zwischen StockContents und sich selbst (StockContents), daher müssten 2 Beziehungen vorliegen.
 
Ich habe mir inzwischen einen Weg ausgedacht, indem ich Einzelteile und Baumgruppen getrennt betrachte. Ist zwar blöd sich sehr ähnliche Datensätze auf zwei Tabellen auf zu teilen, aber so langsam muss mal ne Lösung her. Wenn eine Baugruppe beispielweise 100 verschiedene Einzelteile enthält, ergibt das 100 Einträge in Usage wo die Baugruppennummern gleich sind.
 

Anhänge

  • DB.JPG
    DB.JPG
    55,3 KB · Aufrufe: 15
Solange du nur 2 Ebenen abbilden willst (Einzelteile und Baugruppen) sehe ich da kein Problem. Wenn aber eine Baugruppe mehrere andere Baugruppen beinhalten kann die ihrerseits aus Einzelteilen bestehen wirds unlogisch.
 
VERDAMMT :mad:
hast Recht, daran hatte ich noch garnicht gedacht. Ich fange gleich an meine Objekte in einzelne Dateien zu speichern. Dann hab ich nur noch das Synchronisationsproblem welches mich zwingen würde einen eigenen Server zu proggen... :(
Hat jemand eine Idee die mich noch aus der Klemme holt?
 
VERDAMMT :mad:
hast Recht, daran hatte ich noch garnicht gedacht. Ich fange gleich an meine Objekte in einzelne Dateien zu speichern. Dann hab ich nur noch das Synchronisationsproblem welches mich zwingen würde einen eigenen Server zu proggen... :(
Hat jemand eine Idee die mich noch aus der Klemme holt?

Code:
test=*# select * from stueckliste ;
 ganzes_teil  |  teil  | menge
--------------+--------------+-------
 Auto  | Motor  |  1
 Auto  | Rad  |  4
 Motor  | Zylinderkopf |  1
 Rad  | Schraube  |  5
 Zylinderkopf | Schraube  |  14
(5 rows)

Also, das Auto besteht aus u.a. 4 Rädern und einem Motor. Dieser wiederum aus dem Zylinderkopf, welcher wiederum 14 Schrauben hat. Zu den 4 Rädern gehören auch je 5 Schrauben. Die komplette Stückliste für das Auto:

Code:
test=*# with recursive enthaltene_teile (ganzes_teil, teil, menge) as (
  select ganzes_teil, teil, menge from stueckliste where ganzes_teil = 'Auto'
 union all
  select t.ganzes_teil, t.teil, t.menge * et.menge
  from enthaltene_teile et, stueckliste t
  where t.ganzes_teil=et.teil
)
select teil, sum(menge) as gesamtmenge from enthaltene_teile group by teil;
  teil  | gesamtmenge
--------------+-------------
 Motor  |  1
 Rad  |  4
 Zylinderkopf |  1
 Schraube  |  34
(4 rows)

34 Schrauben (14 Motor und 20 Räder)
 
Werbung:
Zurück
Oben