Datenbank für AnforderungsManagement

RedFerret

Benutzer
Beiträge
24
Hallo,

ich bin neu hier im Forum und brauche ein paar Tipps. Grundlegende Kenntnisse zu Datenbanken habe ich und ich arbeite mit MySQLworkbench.

Ich möchte eine Datenbank erstellen mit der ich für verschiedene Produkte Anforderungen erfassen kann, die sich in Haupt- und Unteranforderungen unterteilen lassen. Ich überlege nun, ob es sinnvoll ist für jedes Produkt eine eigene HauptanforderungsTabelle zu erstellen. Jede dieser Hauptanforderungen müsste sich dann wieder in Unteranforderungen aufspalten. Dann hätte ich eine unübersichtlich große Anzahl an Tabellen, aber Redundanzen vermieden. Die Alternative wäre eine große Tabelle für alle Hauptanforderungen und eine große Tabelle für alle Unteranforderungen, dadurch dann halt Redundanz. Oder hat jemand noch eine ganz andere Idee?

Wenn mir jemand ein paar Tipps geben könnte wäre ich sehr dankbar. Ich möchte nicht dass jemand die Aufgabe für mich löst, nur etwas Beratung. Habe noch nicht viele Datenbanken erstellt.

Bis hier hin schonmal Danke fürs lesen :)
 
Werbung:

akretschmer

Datenbank-Guru
Beiträge
9.423
Hallo,

ich bin neu hier im Forum und brauche ein paar Tipps. Grundlegende Kenntnisse zu Datenbanken habe ich und ich arbeite mit MySQLworkbench.

Ich möchte eine Datenbank erstellen mit der ich für verschiedene Produkte Anforderungen erfassen kann, die sich in Haupt- und Unteranforderungen unterteilen lassen. Ich überlege nun, ob es sinnvoll ist für jedes Produkt eine eigene HauptanforderungsTabelle zu erstellen. Jede dieser Hauptanforderungen müsste sich dann wieder in Unteranforderungen aufspalten. Dann hätte ich eine unübersichtlich große Anzahl an Tabellen,

aber Dein Geschäft könnte nicht mehr wachsen, denn mit jedem neuen Produkt müßtest Du neue Tabellen anlegen und auch die Programmierung der Anwendung anpassen.

aber Redundanzen vermieden.

Wo siehst Du Redundanz?

Die Alternative wäre eine große Tabelle für alle Hauptanforderungen und eine große Tabelle für alle Unteranforderungen, dadurch dann halt Redundanz.

Nochmal: wo siehst Du Redundanz?


Andreas
 

RedFerret

Benutzer
Beiträge
24
Danke für die schnelle Antwort :)

aber Dein Geschäft könnte nicht mehr wachsen, denn mit jedem neuen Produkt müßtest Du neue Tabellen anlegen und auch die Programmierung der Anwendung anpassen.
Andreas

Meine Idee war, beim Anlegen eines neuen Produktes durch einen Trigger eine neue dazu gehörige Anforderungstabelle erstellen zu lassen. Was du mit "Programmierung der Anwendung anpassen" meinst ist mir nicht ganz klar.

Ich denke Redundanz würde auftauchen, wenn ich eine Tabelle für sämtliche Anforderungen hätte, dann müsste nämlich jede Anforderung das Attribut "Produkt" haben, damit man weiß wozu die Anforderung gehört.
 

akretschmer

Datenbank-Guru
Beiträge
9.423
Danke für die schnelle Antwort :)


Meine Idee war, beim Anlegen eines neuen Produktes durch einen Trigger eine neue dazu gehörige Anforderungstabelle erstellen zu lassen. Was du mit "Programmierung der Anwendung anpassen" meinst ist mir nicht ganz klar.

Du hast also eine Tabelle mit den Produkten. Wenn da ein Neues auftaucht, willst Du eine neue Tabelle speziell für dieses Produkt erstellen, ja?

Nun wirst Du ja nicht die ganze Arbeit alles händisch mit SQL machen wollen, sondern Du hast z.B. eine Website mit PHP, mit der Du das bedienst. Diese wirst Du dann vermutlich ändern müssen, damit diese die neuen Tabellen kennt (okay, man kann den Namen sicher auch dynamisch herleiten).

Über wieviele Produkte und über alle Produkte wie viele Anforderungen reden wir?

Das, was Dir wohl vorschwebt, ist Tabellen-Partitionierung. Aber das lohnt erst richtig wenn Du *richtig* viele Daten hast. Nenn also mal 'ne Hausnummer.

Ich denke Redundanz würde auftauchen, wenn ich eine Tabelle für sämtliche Anforderungen hätte, dann müsste nämlich jede Anforderung das Attribut "Produkt" haben, damit man weiß wozu die Anforderung gehört.

Ja, dazu wäre dann natürlich ein Fremdschlüssel auf die Produkttabelle nötig. Daher kommt auch das 'relational' von 'Relationalen Datenbanken' ;-)



Andreas
 

RedFerret

Benutzer
Beiträge
24
Die Anzahl der Datensätze wird bei mir nicht über 10 Produkte hinausgehen, denn es soll nur ein Modell werden und es wird niemals den Weg zur praxistauglichen Anwendung finden. Allerdings soll man nachher nicht sagen können: "Das funktioniert ja nur wenn es nicht viele Datensätze gibt!"

Aber ich denke Du hast mich überzeugt doch besser jeweils eine "große" Tabelle für alle Haupt- und Unteranforderungen zu machen. Kann man dann von einem normalisierten Tabellenmodell sprechen?
 

ukulele

Datenbank-Guru
Beiträge
4.582
Auch an dieser Stelle möchte ich mal noch auf einen meiner Beiträge verweisen: https://www.datenbankforum.com/threads/guid-über-mehere-tabellen.796/ (2ter Beitrag)

Hier (in diesem Thread) scheint mir die selbe Problematik zu Grunde zu liegen. Ich habe eine beliebilge Anzahl nicht gleichartiger Objekte (Produkte) zu verwalten und nicht alle Objekte und deren Eigenschaften sind mir von Anfang an bekannt.

Vieleicht schreibe ich dazu nochmal einen kleinen extra Beitrag wenn ich die Zeit habe um das Anhand von Beispielen besser zu erleutern. Ich habe mit dieser Vorgehensweise das erste mal über unser DMS zu tun gehabt und finde diesen Ansatz logisch und nützlich. Natürlich gibt es Alternativen wie z.B. das Anlegen neuer Tabellen.
 

RedFerret

Benutzer
Beiträge
24
Stehe vor einem neuen Problemchen.

In meinem Modell hat jede Anforderung ein gewissen Zeitbedarf.
Eine HauptAnforderung besteht aus Unteranforderungen und
der Zeitbedarf der HauptAnforderung soll die Summe der Zeitbedarfe ihrer UnterAnforderungen sein.

Da ich sowas noch nie gemacht habe, frage ich mich, wie ich einem Wert "sage", dass er sich aus anderen Werten zusammensetzen soll.

EDIT:

Denke ich habe eine korrekte Lösung gefunden und poste sie mal, falls jemand ein ähnliches Problem haben sollte:

UPDATE HauptAnforderungen
SET ZeitBedarf_Tage = (

SELECT
sum(unteranforderungen.zeitbedarf_tage)
from unteranforderungen
where hauptanforderungen.anforderungsid = unteranforderungen.hauptanforderungsid
)
 

akretschmer

Datenbank-Guru
Beiträge
9.423
Stehe vor einem neuen Problemchen.

In meinem Modell hat jede Anforderung ein gewissen Zeitbedarf.
Eine HauptAnforderung besteht aus Unteranforderungen und
der Zeitbedarf der HauptAnforderung soll die Summe der Zeitbedarfe ihrer UnterAnforderungen sein.

Ähm, ja.

So wie Du das formulierst ist da eher eine Forderung, die einzuhalten ist. Also, Du sagst, die Anforderung hat Zeitbedarf X, die Summe der Zeitbedarfe der Unterforderungen darf das nicht überschreiten. Das wäre natürlich auch abbildbar, aber Deine Lösung ist ja viel trivialer. Und so, wie Du es löst, eigentlich auch wieder falsch, weil nun hast Du Redundanz in Deiner Datenbank. Du kannst also den Zeitbedarf einer Anforderung komplett weglassen und die Summe beim SELECT bilden.


Andreas
 

RedFerret

Benutzer
Beiträge
24
Die Redundanz hatte ich vergessen... hast mal wieder Recht. Das mit dem Zeitbedarf der nicht überschritten werden wäre wirklich eine bessere Alternative. Allerdings hat jedes Produkt an sich schon einen Abgabetermin. Jetzt könnte man vielleicht der HauptAnforderung einen Vorstellungstermin geben, an dem es dem Kunden vorgeführt werden soll.
 

RedFerret

Benutzer
Beiträge
24
Bin dabei einen Trigger zu schreiben aber es gelingt mir leider nicht so ganz.

Meine Anforderungen haben das boolean Attribunt "erledigt". Wenn jetzt jede UnterAnforderung den Wert "erledigt 1" hat, soll die dazugehörige HauptAnforderung auch den Wert 1 bei "erledigt" bekommen. Mit jeweils einer View(Select lässt sich ja im Trigger nicht benutzen) für

HauptAnforderungsID, Anzahl_UnterAnforderungen und
HauptAnforderungsID, Sum_ErledigteUnterAnforderungen

schaffe ich mir zwei Vergleichswerte. Wenn diese übereinstimmen soll das Attribut "erledigt" von der jeweiligen HauptAnforderung auf 1 gesetzt werden.

Ich hab mich jetzt einfach mal an einem Trigger versucht der so aussieht:

DELIMITER //
CREATE TRIGGER erledigung
AFTER UPDATE ON unteranforderungen.erledigt
FOR EACH ROW
BEGIN
IF sum_erledigt.anzahl_erledigt = uanf_pro_hanf.anzahl_uanf ***
THEN SET hauptanforderungen.erledigt = 1;
END IF;
END//
DELIMITER ;

*** sum_erledigt.anzahl_erledigt enthält die summe der erledigt booleans
und uanf_pro_hanf.anzahl enthält die Anzahl der UnterAnforderungen pro HauptAnforderung


Das ist vermutlich totaler Käse, bekomme auch die Fehlermeldung "Error Code: 1193. Unknown system variable 'erledigt'0.000 sec"
aber ich komm einfach ohne Hilfe nicht weiter...
 

akretschmer

Datenbank-Guru
Beiträge
9.423
Bin dabei einen Trigger zu schreiben aber es gelingt mir leider nicht so ganz.

Meine Anforderungen haben das boolean Attribunt "erledigt". Wenn jetzt jede UnterAnforderung den Wert "erledigt 1" hat, soll die dazugehörige HauptAnforderung auch den Wert 1 bei "erledigt" bekommen. Mit jeweils einer View(Select lässt sich ja im Trigger nicht benutzen) für

HauptAnforderungsID, Anzahl_UnterAnforderungen und
HauptAnforderungsID, Sum_ErledigteUnterAnforderungen

schaffe ich mir zwei Vergleichswerte. Wenn diese übereinstimmen soll das Attribut "erledigt" von der jeweiligen HauptAnforderung auf 1 gesetzt werden.

Ich hab mich jetzt einfach mal an einem Trigger versucht der so aussieht:

DELIMITER //
CREATE TRIGGER erledigung
AFTER UPDATE ON unteranforderungen.erledigt
FOR EACH ROW
BEGIN
IF sum_erledigt.anzahl_erledigt = uanf_pro_hanf.anzahl_uanf ***
THEN SET hauptanforderungen.erledigt = 1;
END IF;
END//
DELIMITER ;

*** sum_erledigt.anzahl_erledigt enthält die summe der erledigt booleans
und uanf_pro_hanf.anzahl enthält die Anzahl der UnterAnforderungen pro HauptAnforderung


Das ist vermutlich totaler Käse, bekomme auch die Fehlermeldung "Error Code: 1193. Unknown system variable 'erledigt'0.000 sec"
aber ich komm einfach ohne Hilfe nicht weiter...


Was für eine DB ist bei Dir am Start?

Hier mal 'ne Fingerübung in PostgreSQL:

Code:
test=# create table aufgaben (id serial primary key, erledigt bool default false);
NOTICE:  CREATE TABLE will create implicit sequence "aufgaben_id_seq" for serial column "aufgaben.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "aufgaben_pkey" for table "aufgaben"  
CREATE TABLE                                                                                         
Time: 5,352 ms                                                                                       
test=*# create table unteraufgaben (id serial primary key, aufgabe int references aufgaben, erledigt bool default false);
NOTICE:  CREATE TABLE will create implicit sequence "unteraufgaben_id_seq" for serial column "unteraufgaben.id"          
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "unteraufgaben_pkey" for table "unteraufgaben"            
CREATE TABLE                                                                                                             
Time: 33,343 ms                                                                                                          
test=*# create or replace function trg_aufgabe() returns trigger as $$ begin if (select count(1) from unteraufgaben where aufgabe=new.aufgabe and not erledigt) = 0 then update aufgaben set erledigt = true where id = new.aufgabe; end if; return new; end;$$language plpgsql;                                                        
CREATE FUNCTION                                                                                                                                                     
Time: 17,596 ms                                                                                                                                                     
test=*# create trigger trg1 after update on unteraufgaben for each row execute procedure trg_aufgabe();
CREATE TRIGGER                                                                                         
Time: 0,263 ms                                                                                         
test=*# insert into aufgaben (id) values (1);
INSERT 0 1                                   
Time: 0,427 ms
test=*# insert into aufgaben (id) values (2);
INSERT 0 1
Time: 0,156 ms
test=*# insert into unteraufgaben (id, aufgabe) values (1,1);
INSERT 0 1
Time: 0,700 ms
test=*# insert into unteraufgaben (id, aufgabe) values (2,1);
INSERT 0 1
Time: 0,327 ms
test=*# select * from aufgaben;
 id | erledigt
----+----------
  1 | f
  2 | f
(2 rows)

Time: 0,175 ms
test=*# update unteraufgaben set erledigt = true where id = 1;
UPDATE 1
Time: 0,703 ms
test=*# select * from aufgaben;
 id | erledigt
----+----------
  1 | f
  2 | f
(2 rows)

Time: 0,150 ms
test=*# update unteraufgaben set erledigt = true where id = 2;
UPDATE 1
Time: 0,644 ms
test=*# select * from aufgaben;
 id | erledigt
----+----------
  2 | f
  1 | t
(2 rows)

Time: 0,151 ms


So könnte es also gehen, wenn Ich Dich richtig verstanden habe.


Andreas
 
Werbung:

RedFerret

Benutzer
Beiträge
24
[...]

So könnte es also gehen, wenn Ich Dich richtig verstanden habe.


ja genau so hab ich das gemeint, allerdings benutze ich SQL. Mein Trigger müsste also so funktionieren wie bei dir die function trg_aufgabe(). Das müsste ja dann ungefähr so aussehen:

Code:
DELIMITER //
CREATE TRIGGER erledigung
AFTER UPDATE ON unteranforderungen
BEGIN 
IF (SELECT count(1) FROM unteranforderungen
WHERE hauptanforderungen = new.hauptanforderungen and NOT erledigt
) = 0 
THEN 
UPDATE hauptanforderungen SET erledigt = true 
WHERE id = new.hauptanforderungen; 
END IF;  
END//
DELIMITER ;

Aber ich verstehe nicht was mit count(1) gemeint ist und wie das mit new funktioniert :(
 
Oben