Allgemeine Fragen zu SQLAlchemy und Pandas

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
grubenfox
User
Beiträge: 422
Registriert: Freitag 2. Dezember 2022, 15:49

sparrow hat geschrieben: Donnerstag 18. Mai 2023, 16:33 Noralisierung wirklich gut anhand von Musikalben
:D ...
('Nora' und 'Musik'... da war mal was. Aber das ist hier nun völllig Offtopic!)
Benutzeravatar
grubenfox
User
Beiträge: 422
Registriert: Freitag 2. Dezember 2022, 15:49

grubenfox hat geschrieben: Donnerstag 18. Mai 2023, 00:08 Ich lasse das jetzt (um diese Uhrzeit) mit dem SQL-Beispiel. Dafür habe ich ein Gegenfrage: Wie ist das mit dem

[ich breche hier ab, zu spät, kann nicht mehr klar denken. Vielleicht später, wenn ich wieder wach bin, mehr...]
Was ich da fragen wollte:

Wie ist das mit dem

Code: Alles auswählen

materials (22) [Materialien mit Zuordnungen der Kunden (Materialdaten kommen von der datanorm)] 
"(Materialdaten kommen von der datanorm)" gemeint? Gibt es da eine View die die Daten aus der Tabelle 'materials' und den dazugehörigen Daten aus 'datanorm' zurückliefert? Oder eine Python-Funktion/Methode?
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

sparrow hat geschrieben: Donnerstag 18. Mai 2023, 16:33 @Kalysto: Ja klar bleibt eine manufacturer_id in der Tabelle. Aber du hast andere Spalten, die sich ebenfalls auf den Hersteller beziehen. Die müssen aus der Tabelle raus. "Manufacturer" ist eine eigene Relation. Und darin enthalten ist u.a. der Name.

Wie gesagt, lies bitte den Wikipedia-Artikel. Der erklärt Noralisierung wirklich gut anhand von Musikalben.

Ich sehe das ebenso, wie andere Leute hier im Thread. Du verwechselst eine relationale Datenbank mit einer Tabellenkalkulation.
Und ich sehe auch nicht, warum man hier Pandas benutzen muss. Ich würde das mit einer vernünftigen und sauberen Datenbankstruktur aufsetzen und SQLAlchemy benutzen. Den Mehrwert von Pandas sehe ich hier nicht.
Pandas werde ich jetzt verwenden um einfacher auf die Daten zurückgreifen zu können:

Code: Alles auswählen

df = pd.read_sql('SELECT * FROM datanorm', con=db_connection, index_col = 'ID')

print(df.loc[31]['qr_codes'])
etc.
.
..
...
....
muss somit keine Arrays selbst erstellen
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

grubenfox hat geschrieben: Donnerstag 18. Mai 2023, 17:15
grubenfox hat geschrieben: Donnerstag 18. Mai 2023, 00:08 Ich lasse das jetzt (um diese Uhrzeit) mit dem SQL-Beispiel. Dafür habe ich ein Gegenfrage: Wie ist das mit dem

[ich breche hier ab, zu spät, kann nicht mehr klar denken. Vielleicht später, wenn ich wieder wach bin, mehr...]
Was ich da fragen wollte:

Wie ist das mit dem

Code: Alles auswählen

materials (22) [Materialien mit Zuordnungen der Kunden (Materialdaten kommen von der datanorm)] 
"(Materialdaten kommen von der datanorm)" gemeint? Gibt es da eine View die die Daten aus der Tabelle 'materials' und den dazugehörigen Daten aus 'datanorm' zurückliefert? Oder eine Python-Funktion/Methode?
Das war so gemeint wenn ich mit der App Materialien in die materials Tabelle hinzufüge das diese Daten von der datanorm stammen und nicht händisch etc. eingetragen werden.

und eine View gibt es die sich einmal eben auf die komplette datanorm bezieht und eben auf ein Kundenprojekt welches dann auf die materials Daten zurück greift.
Benutzeravatar
sparrow
User
Beiträge: 4185
Registriert: Freitag 17. April 2009, 10:28

@grubenfox: Ja Mensch, lustig.

@Kalysto: Vergiss Pandas in diesem Zusammenhang. Du musst auch keine Arrays selber bauen. SQLAlchemy kann neben dem rohen SQL-Zugriff ORM. Arbeite das Tutorial durch. Das was du da versuchst scheint eher so, als würdest du entweder das falsche Backend für Pandas verwenden (das wurde hier auch schon gesagt. Wenn du nicht bereit bist eine relationale Datenbank zu relational zu verwenden, dann solltest du gar keine verwenden) oder du missbrauchst Pandas als ORM, wofür du denfinitiv SQLAlchemy direkt nehmen solltest.
In der Konstellation, wie du es verwendest, halte ich das für völlig falsch.
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

sparrow hat geschrieben: Donnerstag 18. Mai 2023, 19:15 @grubenfox: Ja Mensch, lustig.

@Kalysto: Vergiss Pandas in diesem Zusammenhang. Du musst auch keine Arrays selber bauen. SQLAlchemy kann neben dem rohen SQL-Zugriff ORM. Arbeite das Tutorial durch. Das was du da versuchst scheint eher so, als würdest du entweder das falsche Backend für Pandas verwenden (das wurde hier auch schon gesagt. Wenn du nicht bereit bist eine relationale Datenbank zu relational zu verwenden, dann solltest du gar keine verwenden) oder du missbrauchst Pandas als ORM, wofür du denfinitiv SQLAlchemy direkt nehmen solltest.
In der Konstellation, wie du es verwendest, halte ich das für völlig falsch.
Okay, dann schau ich mir die SQLAlchemy ORM einmal an wie das dort funktioniert.

auf die Datenbank nun einmal erst zurück, wenn ich nun meine Kundentabelle als bsp. nehme:
  • EE-7E4-3744 (DB-Name)
    • customers (13) [Angaben aller Kunden] / Einträge gesamt: 62
      • Tabelle_id / int(11) / AUTO_INCREMENT
      • Kundennummer / int(4)
      • Firma / tinyint(1)
      • Favorit / tinyint(1)
      • Benutzername / varchar(20)
      • Benutzername_update / varchar(20)
      • Firmenname / varchar(50)
      • Vorname / varchar(15)
      • Nachname / varchar(15)
      • Ort / varchar(25)
      • Kundenprojekte / varchar(255)
      • Erstellungsdatum / date
      • Aktualisierungsdatum / date
ich weis einfach nicht wie ich das umsetzten soll in meinem Beispiel.

Firma (Eintragungen sind hier 1 oder 0)
Favorit (Eintragungen sind hier 1 oder 0)
Benutzername (Sind mehrfach benannt)
Benutzername_update (Sind mehrfach benannt)
Firmenname (Könnte doppelt vorkommen)
Vorname (Könnte doppelt vorkommen)
Nachname (Könnte doppelt vorkommen)
Ort (Gibt es gleichnamige)
Kundenprojekte (Gibt es gleichnamige)
Erstellungsdatum (Gibt es gleichnamige)
Aktualisierungsdatum (Gibt es gleichnamige)

ab wann muss oder sollte man das aufsplittern in mehreren Tabellen.

Sollte ich dann z.b. den Ort und das Kundenprojekte in eine eigene Tabelle schreiben und anhand ID's "verknüpfen" sodass es in Ordnung wäre ?


NACHTRAG:
Was mir noch eingefallen ist sollte ich z.b. in meiner `users` Tabelle meinen Benutzern eindeutige ID's erstellen und mit diesen nur auf meine Tabelle verweisen anstatt immer den Namen einzutragen ?
Xbash_Zero
User
Beiträge: 30
Registriert: Montag 19. September 2022, 22:48

ab wann muss oder sollte man das aufsplittern in mehreren Tabellen.
Beim relationalen Datenbankdesign sollte man versuchen, gar keine Duplikate oder Redundanzen zu erhalten. Du kannst versuchen, kleinere Tabellen zu machen, ich habe mir immer einen Plan gezeichnet, sowas wie das hier:

Bild


Zum ORM:

Du bildest deine Datenbank in Python ab, keine Ahnung, ob das hier schon erwähnt wurde, habe nur den ersten und letzten Beitrag von dir gelesen.

Code: Alles auswählen

from sqlalchemy import create_engine, Column, Integer, String, Boolean, ForeignKey, Date
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship

# Verbindung zur Datenbank herstellen
engine = create_engine('your_database_url')
Base = declarative_base()


class Customer(Base):
    __tablename__ = 'customers'

    id = Column(Integer, primary_key=True, autoincrement=True)
    customer_id = Column(Integer, unique=True)
    is_company = Column(Boolean)
    is_favorite = Column(Boolean)
    user_name = Column(String)
    user_name_update = Column(String)
    company = Column(String)
    first_name = Column(String)
    last_name = Column(String)
    place = Column(String)
    customer_projects = relationship('Project', back_populates='customer')
    date_create = Column(Date)
    date_update = Column(Date)


class Datanorm(Base):
    __tablename__ = 'datanorm'

    id = Column(Integer, primary_key=True, autoincrement=True)
    qr_code = Column(String)
    ean_code = Column(String)
    user_name = Column(String)
    user_name_update = Column(String)
    sort_number = Column(Integer)
    manufacturer_id = Column(Integer, ForeignKey('manufacturers.manufacturer_id'))
    manufacturer = Column(String)
    manufacturer_designation = Column(String)
    manufacturer_designation_short = Column(String)
    manufacturer_number = Column(String)
    supplier_xyz_number = Column(String)
    deactivated_xyz = Column(Boolean)
    supplier_other_number = Column(String)
    supplier_other_name = Column(String)
    deactivated_other = Column(Boolean)
    count = Column(Integer)
    material_inventory = Column(Integer)
    per_piece = Column(String)
    purchasing_price = Column(Float)
    selling_price = Column(Float)
    update_price = Column(Date)
    cutting = Column(Boolean)
    inventory = Column(String)
    inventory_lite = Column(String)
    inventory_query = Column(String)
    inventory_order_quantity = Column(Integer)
    date_create = Column(Date)
    date_update = Column(Date)
    date_out = Column(Date)


class Manufacturer(Base):
    __tablename__ = 'manufacturers'

    id = Column(Integer, primary_key=True, autoincrement=True)
    manufacturer_id = Column(Integer, unique=True)
    user_name = Column(String)
    user_name_update = Column(String)
    manufacturer = Column(String)
    area_from = Column(Integer)
    area_to = Column(Integer)
    in_use = Column(Boolean)
    max_use = Column(Integer)
    date_create = Column(Date)
    date_update = Column(Date)
    materials = relationship('Datanorm', back_populates='manufacturer')


class Material(Base):
    __tablename__ = 'materials'

    id = Column(Integer, primary_key=True, autoincrement=True)
    datanorm_id = Column(Integer, ForeignKey('datanorm.id'))
    customer_id = Column(Integer, ForeignKey('customers.customer_id'))
    project_id = Column(Integer, ForeignKey('projects.project_id'))
    user_name = Column(String)
    user_name_update = Column(String)
    sort_number = Column(Integer)
    manufacturer_id = Column(Integer, ForeignKey('manufacturers.manufacturer_id'))
    manufacturer = Column(String)
    manufacturer_designation = Column(String)
    manufacturer_designation_short = Column(String)
    manufacturer_number = Column(String)
    supplier_xyz_number = Column(String)
    supplier_other_number = Column(String)
    comment = Column(String)
    count = Column(Integer)
    count_interim_bill = Column(Integer)
    selling_price = Column(Float)
    update_price = Column(Date)
    date_create = Column(Date)
    date_update = Column(Date)
    date_closed = Column(Date)


class Project(Base):
    __tablename__ = 'projects'

    id = Column(Integer, primary_key=True, autoincrement=True)
    customer_id = Column(Integer, ForeignKey('customers.customer_id'))
    project_id = Column(Integer, unique=True)
    user_name = Column(String)
    user_name_update = Column(String)
    user_name_closed = Column(String)
    customer_project = Column(String)
    interim_bill = Column(Boolean)
    closed = Column(Boolean)
    date_create = Column(Date)
    date_update = Column(Date)
    date_closed = Column(Date)
    customer = relationship('Customer', back_populates='customer_projects')


class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True, autoincrement=True)
    device_id = Column(String)
    name = Column(String)
    mail = Column(String)
    role = Column(String)
    password = Column(String)


class Version(Base):
    __tablename__ = 'version'

    id = Column(Integer, primary_key=True, autoincrement=True)
    file = Column(String)
    version = Column(String)
    build = Column(String)
    file_stamp = Column(String)
    update_needed = Column(Boolean)
    update_price = Column(Integer)


# Die Tabellen erstellen
Base.metadata.create_all(engine)
Xbash_Zero
User
Beiträge: 30
Registriert: Montag 19. September 2022, 22:48

[...] ab wann muss oder sollte man das aufsplittern (sic!) in mehreren Tabellen.
Beim relationalen Datenbankdesign sollte man versuchen, gar keine Duplikate oder Redundanzen zu erhalten. Du kannst versuchen, kleinere Tabellen zu machen, ich habe mir immer einen Plan gezeichnet, sowas wie das hier:

Bild

Die Tabellen zu minimieren ist der komplizierte Schritt, das erfordert eine höhere Abstraktion. Die Verknüpfung der ID's sieht doch eigentlich schon gut aus, mache halt überall statt user_name eine User-ID, um das mit dem Update, Eintragung oder Löschen zu verknüpfen. In den relevanten Tabellen machst du Spalten wie: User-ID-create, User-ID-update, User-ID-closed usw...

Sollte ich dann z.b. den Ort und das Kundenprojekte in eine eigene Tabelle schreiben und anhand ID's "verknüpfen" sodass es in Ordnung wäre ?
Das wäre eine Möglichkeit, Tabelle Ort mit den Spalten ID, User-ID, Kunden-ID, Hersteller-ID, Ort-ID, Adresse, PLZ, Straße etc., damit könntest du die Orte von Projekten, Kunden und Usern verknüpfen... und entsprechend auch per Query selektiv oder allgemein abrufen.


Zum ORM:

Du bildest deine Datenbank in Python ab, keine Ahnung, ob das hier schon erwähnt wurde, habe nur den ersten und letzten Beitrag von dir gelesen.

Hier, so würde es aussehen, bezogen auf deinen ersten Beitrag hier im Thread:

Code: Alles auswählen

from sqlalchemy import create_engine, Column, Integer, String, Boolean, ForeignKey, Date
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship

# Verbindung zur Datenbank herstellen
engine = create_engine('your_database_url')
Base = declarative_base()


class Customer(Base):
    __tablename__ = 'customers'

    id = Column(Integer, primary_key=True, autoincrement=True)
    customer_id = Column(Integer, unique=True)
    is_company = Column(Boolean)
    is_favorite = Column(Boolean)
    user_name = Column(String)
    user_name_update = Column(String)
    company = Column(String)
    first_name = Column(String)
    last_name = Column(String)
    place = Column(String)
    customer_projects = relationship('Project', back_populates='customer')
    date_create = Column(Date)
    date_update = Column(Date)


class Datanorm(Base):
    __tablename__ = 'datanorm'

    id = Column(Integer, primary_key=True, autoincrement=True)
    qr_code = Column(String)
    ean_code = Column(String)
    user_name = Column(String)
    user_name_update = Column(String)
    sort_number = Column(Integer)
    manufacturer_id = Column(Integer, ForeignKey('manufacturers.manufacturer_id'))
    manufacturer = Column(String)
    manufacturer_designation = Column(String)
    manufacturer_designation_short = Column(String)
    manufacturer_number = Column(String)
    supplier_xyz_number = Column(String)
    deactivated_xyz = Column(Boolean)
    supplier_other_number = Column(String)
    supplier_other_name = Column(String)
    deactivated_other = Column(Boolean)
    count = Column(Integer)
    material_inventory = Column(Integer)
    per_piece = Column(String)
    purchasing_price = Column(Float)
    selling_price = Column(Float)
    update_price = Column(Date)
    cutting = Column(Boolean)
    inventory = Column(String)
    inventory_lite = Column(String)
    inventory_query = Column(String)
    inventory_order_quantity = Column(Integer)
    date_create = Column(Date)
    date_update = Column(Date)
    date_out = Column(Date)


class Manufacturer(Base):
    __tablename__ = 'manufacturers'

    id = Column(Integer, primary_key=True, autoincrement=True)
    manufacturer_id = Column(Integer, unique=True)
    user_name = Column(String)
    user_name_update = Column(String)
    manufacturer = Column(String)
    area_from = Column(Integer)
    area_to = Column(Integer)
    in_use = Column(Boolean)
    max_use = Column(Integer)
    date_create = Column(Date)
    date_update = Column(Date)
    materials = relationship('Datanorm', back_populates='manufacturer')


class Material(Base):
    __tablename__ = 'materials'

    id = Column(Integer, primary_key=True, autoincrement=True)
    datanorm_id = Column(Integer, ForeignKey('datanorm.id'))
    customer_id = Column(Integer, ForeignKey('customers.customer_id'))
    project_id = Column(Integer, ForeignKey('projects.project_id'))
    user_name = Column(String)
    user_name_update = Column(String)
    sort_number = Column(Integer)
    manufacturer_id = Column(Integer, ForeignKey('manufacturers.manufacturer_id'))
    manufacturer = Column(String)
    manufacturer_designation = Column(String)
    manufacturer_designation_short = Column(String)
    manufacturer_number = Column(String)
    supplier_xyz_number = Column(String)
    supplier_other_number = Column(String)
    comment = Column(String)
    count = Column(Integer)
    count_interim_bill = Column(Integer)
    selling_price = Column(Float)
    update_price = Column(Date)
    date_create = Column(Date)
    date_update = Column(Date)
    date_closed = Column(Date)


class Project(Base):
    __tablename__ = 'projects'

    id = Column(Integer, primary_key=True, autoincrement=True)
    customer_id = Column(Integer, ForeignKey('customers.customer_id'))
    project_id = Column(Integer, unique=True)
    user_name = Column(String)
    user_name_update = Column(String)
    user_name_closed = Column(String)
    customer_project = Column(String)
    interim_bill = Column(Boolean)
    closed = Column(Boolean)
    date_create = Column(Date)
    date_update = Column(Date)
    date_closed = Column(Date)
    customer = relationship('Customer', back_populates='customer_projects')


class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True, autoincrement=True)
    device_id = Column(String)
    name = Column(String)
    mail = Column(String)
    role = Column(String)
    password = Column(String)


class Version(Base):
    __tablename__ = 'version'

    id = Column(Integer, primary_key=True, autoincrement=True)
    file = Column(String)
    version = Column(String)
    build = Column(String)
    file_stamp = Column(String)
    update_needed = Column(Boolean)
    update_price = Column(Integer)


# Die Tabellen erstellen
Base.metadata.create_all(engine)
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

@ Xbash_Zero vielen dank für deine Mühe, nun habe ich erst einmal ein Anhaltspunkt wie ich starten muss und wie es aussehen sollte/kann.
Ich werde mir dein Code einmal anschauen und verinnerlichen und bei Fragen bzw. wenn ich soweit bin werde ich mich hier wieder melden und zu fragen ob das so in Ordnung ist mein DB-Aufbau.

DANKE! :!:
Antworten