Mehrere gleiche Werte in DB

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
paddie
User
Beiträge: 101
Registriert: Donnerstag 11. Oktober 2018, 18:09

Weniger eine Python-, sondern eher eine DB-Design-Frage..

Ich möchte verschiedene Produkte in einer DB speichern. Unter anderem Lampen, welche entweder eine quadratische, rechteckige oder runde Grundfläche haben und dazu passende LED-Treiber, welche eine rechteckige Grundfläche haben.

So sieht mein Model im Moment aus

Code: Alles auswählen

class Product(Base, db.Model):
    __tablename__ = 'product'
    item_id = db.Column(db.String(100), primary_key=True)
    length = db.Column(db.Integer)
    width = db.Column(db.Integer)
    height = db.Column(db.Integer)
    diameter = db.Column(db.Integer)
    weight = db.Column(db.DECIMAL)
...
...

class Lamp(Product):
    __tablename__ = 'lamp'
    id = db.Column(db.String(100), ForeignKey(Product.item_id), primary_key=True)
...
...

class Driver(Product):
    __tablename__ = 'driver'
    id = db.Column(db.String(100), ForeignKey(Product.item_id), primary_key=True)
...
...
Es soll in Abhängigkeit ob rund oder eckig entweder Länge, Breite und Höhe ODER der Durchmesser und Höhe ausgefüllt werden. Die nicht benötigten Felder lasse ich leer. Hier sehe ich ja eigentlich noch kein Problem, oder?

Allerdings habe ich auch viele Artikel mit den gleichen Abmessungen..deshalb meine Idee... Ich erstelle eine extra Tabelle in der ich die Abmessungen und Gewichte speicher mit folgenden Feldern

ID | length | width | heigth | diameter | weigth

und mache in mein Formular für die Product-Eingabe ein Auswahlfeld für die schon vorhandenen Abmessungen und, falls, das gewünschte nicht vorhanden ist, leg ich es neu an.
Was mir daran nicht wirklich gefällt: Die Liste wird irgendwann sehr unübersichtlich.

Hat vielleicht jemand einen Tip, was hier eine bessere Lösung wäre?

Danke

Paddie
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Vererbung verstehe ich nicht. Du hast eine Tabelle product und Tabellen lamp und driver?
Warum drei Tabellen? In was unterscheiden sich die Tabellen?
Was hast das Gewicht mit den Abmessungen zu tun?
Fehlt da nicht noch eine Feld für die Form?
Ich dachte Driver sind immer rechteckig? Was soll dann da der Durchmesser?
IDs als Strings sind suboptimal.
paddie
User
Beiträge: 101
Registriert: Donnerstag 11. Oktober 2018, 18:09

OK, ich hätte doch die Gesamten Klassen reinkopieren sollen ;-) ...

Code: Alles auswählen

class Product(db.Model):
    __tablename__ = 'product'
    item_id = db.Column(db.String(100), primary_key=True)
    short_text = db.Column(db.String(250))
    customs_tariff_no = db.Column(db.Integer)
    gtin = relationship("GTIN", uselist=False, back_populates="product")
    active = db.Column(db.Boolean, default=True)
    length = db.Column(db.Integer)
    width = db.Column(db.Integer)
    height = db.Column(db.Integer)
    diameter = db.Column(db.Integer)
    weight = db.Column(db.DECIMAL)
    list_price = db.Column(db.DECIMAL)
    min_ambient_temperature = db.Column(db.Integer)
    max_ambient_temperature = db.Column(db.Integer)

    type = db.Column(db.String(50))

    __mapper_args__ = {
        'polymorphic_on': "type"
    }

class Lamp(Product):
    __tablename__ = 'lamp'
    id = db.Column(db.String(100), ForeignKey(Product.item_id), primary_key=True)
    driver_included = db.Column(db.Boolean)
    lum_flux = db.Column(db.Integer)
    ip_code = db.Column(db.String(4))
    power = db.Column(db.Integer)
    radiation_angle = db.Column(db.Integer)
    average_lifespan = db.Column(db.String(10))
    power_factor = db.Column(db.String(10))
    ugr = db.Column(db.String(3))
    dimmable = db.Column(db.Boolean)

    __mapper_args__ = {
        'polymorphic_identity': 'lamp'
    }

class Driver(Product):
    __tablename__ = 'driver'
    id = db.Column(db.String(100), ForeignKey(Product.item_id), primary_key=True)
    supplier_item_id = db.Column(db.String(25))
    nominal_current = db.Column(db.Integer)
    u_out = db.Column(db.Integer)
    u_out_max = db.Column(db.Integer)
    p_max = db.Column(db.Integer)
    control = db.Column(db.String(20))

    __mapper_args__ = {
        'polymorphic_identity': 'driver',
    }

Fehlt da nicht noch eine Feld für die Form?
Vielleicht auch eher eine dumme Idee...wenn ich ja den Radius eingebe sollte ja klar sein, dass es rund ist ;-) ..Aber wenn ich das so recht überlege ist das wirklich etwas doof ..
Ich dachte Driver sind immer rechteckig? Was soll dann da der Durchmesser?
Das ist ja das, was ich geschreiben hab, das Feld würde ich dann leer lassen
Oder sollte ich das eher mit der Vererbung lösen, dass ich die Abmessungen nicht in Product speichere sondern jeweils in Lamp und Driver?? Wäre vielleicht eher sinnvoll. DANN würde praktisch nur die Höhe in Product stehen, weil die ja bei allen dabei ist.
IDs als Strings sind suboptimal.
Leider sind die "Artikel-Nummern" hier Kombinationen aus Buchstaben und Zahlen. Mein Gedanke war, wieso soll ich da noch zusätzlich eine "normale" ID verwenden. Auto Increment kann ich eh nicht machen.
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@paddie: Ich sehe diese Extra-Tabelle nicht wirklich. Das macht alles nur komplizierter, wenn man beispielsweise feststellt, dass bei einem Datensatz die Höhe falsch ist, kann man die nicht einfach anpassen, sondern muss erst einmal schauen ob es in der Tabelle mit den Massen das neue Mass bereits gibt, falls nicht einen neuen Eintrag anlegen, und dann schauen ob das alte Mass noch von irgendwem benutzt wird, falls nicht das löschen. Das alles für eine Änderung von einem Zahlwert.

Du solltest eine zusätzliche ”normale” ID machen weil Datenbanken das erwarten und damit effizient umgehen können. Ich kenne aus der Praxis eigentlich so gut wie 100% künstliche Primärschlüssel. Es ist eher selten das da ein Wert aus der Problemdomäne genommen wird. Weil früher oder später ändert der sich dann doch mal und dann hat man ”Spass” das alles in den Daten gerade zu biegen.

Zwei Beispiele mit denen ich schon konfrontiert war: DB benutzt Postleitzahlen als Primärschlüssel/Fremdschlüssel weil die sind ja immer vierstellig und ändern sich nicht. Mal davon abgesehen dass das auch vor der Wiedervereinigung nicht ganz stimmte, gab's mit der Umstellung auf die fünfstelligen PLZs dann viel Spass. Zweites Beispiel Produktnummern eines Unternehmens. Das Unternehmen wurde aufgekauft und tadaa: die ach so festen, eindeutigen Produktnummern wurden alle dem Muster des neuen Mutterunternehmens angepasst.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
paddie
User
Beiträge: 101
Registriert: Donnerstag 11. Oktober 2018, 18:09

__blackjack__ hat geschrieben: Mittwoch 26. Februar 2020, 12:24 @paddie: Ich sehe diese Extra-Tabelle nicht wirklich. Das macht alles nur komplizierter, wenn man beispielsweise feststellt, dass bei einem Datensatz die Höhe falsch ist, kann man die nicht einfach anpassen, sondern muss erst einmal schauen ob es in der Tabelle mit den Massen das neue Mass bereits gibt, falls nicht einen neuen Eintrag anlegen, und dann schauen ob das alte Mass noch von irgendwem benutzt wird, falls nicht das löschen. Das alles für eine Änderung von einem Zahlwert.
Ach, du meinst die Tabelle mit den Abmessungen und Gewicht. DIE existiert noch nicht, das war ja mit der Grund meiner Frage ob das vielleicht mehr Sinn ergibt ;-).
Du solltest eine zusätzliche ”normale” ID machen weil Datenbanken das erwarten und damit effizient umgehen können. Ich kenne aus der Praxis eigentlich so gut wie 100% künstliche Primärschlüssel. Es ist eher selten das da ein Wert aus der Problemdomäne genommen wird. Weil früher oder später ändert der sich dann doch mal und dann hat man ”Spass” das alles in den Daten gerade zu biegen.

Zwei Beispiele mit denen ich schon konfrontiert war: DB benutzt Postleitzahlen als Primärschlüssel/Fremdschlüssel weil die sind ja immer vierstellig und ändern sich nicht. Mal davon abgesehen dass das auch vor der Wiedervereinigung nicht ganz stimmte, gab's mit der Umstellung auf die fünfstelligen PLZs dann viel Spass. Zweites Beispiel Produktnummern eines Unternehmens. Das Unternehmen wurde aufgekauft und tadaa: die ach so festen, eindeutigen Produktnummern wurden alle dem Muster des neuen Mutterunternehmens angepasst.
OK, DAS habe ich so noch nicht bedacht. Dann eine gesonderte ID-Spalte und die Item-ID mit unique constraint?
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@paddie: Ich denke du hast den ersten Satz zu wörtlich genommen: Ich meinte damit nicht das ich die Tabelle nicht sehe sondern das ich nicht sehe dass das Sinn macht. :-)
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
DeaD_EyE
User
Beiträge: 1017
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Lass die Datenbank die id selbständig erstellen. Die ProduktID nicht als PrimärSchlüssel vergeben. Primärschlüssel dürfen nur einmal vorkommen.
Mit doppelten Einträgen wird das nicht funktionieren, wenn die ProduktID ein Primärschlüssel ist.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
paddie
User
Beiträge: 101
Registriert: Donnerstag 11. Oktober 2018, 18:09

DeaD_EyE hat geschrieben: Mittwoch 26. Februar 2020, 14:34 Lass die Datenbank die id selbständig erstellen. Die ProduktID nicht als PrimärSchlüssel vergeben. Primärschlüssel dürfen nur einmal vorkommen.
Das habe ich jetzt schon geändert ;-). Das der Primärschlüssel nur einmal vorkommen darf ist mir bewusst.
Mit doppelten Einträgen wird das nicht funktionieren, wenn die ProduktID ein Primärschlüssel ist.
Es ging mir eher darum, dass die item_id (welche ich vorher als Primärschlüssel hatte) nicht doppelt sein darf. Weil das halt die hier benutzten Artikel-Nummern sind, die ich nicht wirklich ändern kann ;-).
paddie
User
Beiträge: 101
Registriert: Donnerstag 11. Oktober 2018, 18:09

So wie ich das jetzt sehe, lass ich es besser so wie es ist (also Abmessungen und Gewicht in der Klasse Product).
Zum einfacheren Suchen würde ich höchstens noch ein Attribut für die Form dazunehmen...und dann in Abhängigkeit davon mein Eingabe-Form ändern. Hier habe ich dann im schlimmsten Fall halt Felder in der DB die leer sind.

Danke schonmal bis hierhin

Paddie
Antworten