Seite 1 von 1
sqlalchemy-postgresql, join 5 tbl, f-key von einer in zwei
Verfasst: Dienstag 13. April 2021, 12:27
von rascha
Hallo! ich bin neu hier mit einem query-problem,
5 tabellen wie folgt a, b, c, d, e:
a: id, col1...
b: id, (foreign-key=a.id), col..
c: id, (foreign-key=a.id), col..
d: id, (foreign-key=b.id), col..
e: id, (foreign-key=c.id), col..
wie soll die abfrage auschauen, so dass auf jeden fall alle Einträge und zwar nicht wiederholt sondern korrect und identifizierbar drin sind?! danke
Re: sqlalchemy-postgresql, join 5 tbl, f-key von einer in zwei
Verfasst: Dienstag 13. April 2021, 12:53
von Sirius3
Ich verstehe Deine Frage nicht. Welche Abfrage? Was sind alle Einträge? Und was bedeutet "korrekt"?
Re: sqlalchemy-postgresql, join 5 tbl, f-key von einer in zwei
Verfasst: Dienstag 13. April 2021, 13:14
von rascha
Hallo vielen dank für die Meldung! eine Abfrage, die alle tabellen joint unter a tabelle, d.h a hat ja fremd-key in b und c, b und c haben wiederum fremd-key in d und e.
ein resultat, die alle einträge von a-tabelle beinhaltet und darunter Einträge von b und c (zugeordnet zu a-id) und unter denen auch einträge von e und d (zugeordnet zu jeweils b-id , c-id)
Re: sqlalchemy-postgresql, join 5 tbl, f-key von einer in zwei
Verfasst: Dienstag 13. April 2021, 16:06
von __blackjack__
@rascha: Und das Problem ist jetzt genau welches? Man joint halt alle Tabellen und gut ist.
Code: Alles auswählen
...
print(
table_a.join(table_b)
.join(table_c)
.join(table_d)
.join(table_e)
.select()
.execute()
.fetchall()
)
Re: sqlalchemy-postgresql, join 5 tbl, f-key von einer in zwei
Verfasst: Dienstag 13. April 2021, 17:18
von rascha
__blackjack__ hat geschrieben: Dienstag 13. April 2021, 16:06
@rascha: Und das Problem ist jetzt genau welches? Man joint halt alle Tabellen und gut ist.
Code: Alles auswählen
...
print(
table_a.join(table_b)
.join(table_c)
.join(table_d)
.join(table_e)
.select()
.execute()
.fetchall()
)
Hallo! vielen Dank für dein Input!
in sqlalchemy bin ich neu unterwegs. ich verwende db-session und zwar so:
database_url = "postgre_db_url"
engine = create_engine(
database_url
)
session_local = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
def get_db():
db = SessionLocal()
try:
yield db
except HTTPException:
db.close()
class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
col1 = Column(String, nullable=False)
def example(db: Session = Depends(get_db)):
db.query(A).join(B).join(C).join(D).all()
und wenn ich da alles in dieser form wie du sagst joine , dann bekomme ich nur die a-tabelle!
l.g
Re: sqlalchemy-postgresql, join 5 tbl, f-key von einer in zwei
Verfasst: Dienstag 13. April 2021, 21:10
von __blackjack__
@rascha: Das ist nicht das gleiche. Du fragst `A` ab und joinst die anderen Tabellen, mein Code joint erst alle Tabellen und fragt die dann ab. Aber das funktioniert beim ORM ja sowieso alles komplett anders. Hättest Du ruhig erwähnen können das Du gar keine Tabellen abfragst sondern Objekte.
Was willst Du denn eigentlich machen hier? Wenn die Abhängigen Objekte generell gleich bei der ersten Abfrage mitgeladen werden sollen, oder nur in diesem speziellen Fall, dann kann man das an entsprechender Stelle angeben.
Edit: Wobei ich mich gerade Frage ob das was Du da machst, nicht auch schon das richtige macht. Was genau gefällt Dir an dem Ergebnis denn nicht?
Edit2: Warum willst Du das eigentlich machen? Premature optimization?
Re: sqlalchemy-postgresql, join 5 tbl, f-key von einer in zwei
Verfasst: Mittwoch 14. April 2021, 10:44
von rascha
__blackjack__ hat geschrieben: Dienstag 13. April 2021, 21:10
@rascha: Das ist nicht das gleiche. Du fragst `A` ab und joinst die anderen Tabellen, mein Code joint erst alle Tabellen und fragt die dann ab. Aber das funktioniert beim ORM ja sowieso alles komplett anders. Hättest Du ruhig erwähnen können das Du gar keine Tabellen abfragst sondern Objekte.
Was willst Du denn eigentlich machen hier? Wenn die Abhängigen Objekte generell gleich bei der ersten Abfrage mitgeladen werden sollen, oder nur in diesem speziellen Fall, dann kann man das an entsprechender Stelle angeben.
Edit: Wobei ich mich gerade Frage ob das was Du da machst, nicht auch schon das richtige macht. Was genau gefällt Dir an dem Ergebnis denn nicht?
Edit2: Warum willst Du das eigentlich machen? Premature optimization?
Hi! kann sein, dass du den komplozierten Punkt hier ausser Acht gelassen hast? nämlich, dass f-key von a in b und c (i beiden) gibt.
das resultat wird abhängig davon welche a-key jeweils in a oder b eingefügt wurde!
das macht es schwirig objecte entsprechend ohne wiederholungen unter a-tabelle zu bringen.
Re: sqlalchemy-postgresql, join 5 tbl, f-key von einer in zwei
Verfasst: Mittwoch 14. April 2021, 11:22
von __blackjack__
@rascha: Das habe ich schon gesehen. `join()` funktioniert nicht. Aber a) einfach ``all_a = session.query(A).all()`` funktioniert, eben mit abfragen/nachladen wie es bei den `relationships()` definiert ist, und falls da der Standard definiert ist, also "select" beim Zugriff auf die Attribute, oder man gibt als Option bei der Abfrage an, dass alle `relationships()` per JOIN in der gleichen Abfrage geladen werden sollen: ``all_a = session.query(A).options(joinedload("*")).all()``. Beispiel, folgende Datenbank:
Code: Alles auswählen
CREATE TABLE a (
id INTEGER NOT NULL,
value TEXT,
PRIMARY KEY (id)
);
INSERT INTO a VALUES(1,'a 1');
INSERT INTO a VALUES(2,'a 2');
CREATE TABLE b (
id INTEGER NOT NULL,
a_id INTEGER,
value TEXT,
PRIMARY KEY (id),
FOREIGN KEY(a_id) REFERENCES a (id)
);
INSERT INTO b VALUES(1,1,'b 1');
INSERT INTO b VALUES(2,2,'b 2');
CREATE TABLE c (
id INTEGER NOT NULL,
a_id INTEGER,
value TEXT,
PRIMARY KEY (id),
FOREIGN KEY(a_id) REFERENCES a (id)
);
INSERT INTO c VALUES(1,1,'c 1');
INSERT INTO c VALUES(2,2,'c 2');
CREATE TABLE d (
id INTEGER NOT NULL,
b_id INTEGER,
value TEXT,
PRIMARY KEY (id),
FOREIGN KEY(b_id) REFERENCES b (id)
);
INSERT INTO d VALUES(1,1,'d 1');
INSERT INTO d VALUES(2,2,'d 2');
CREATE TABLE e (
id INTEGER NOT NULL,
c_id INTEGER,
value TEXT,
PRIMARY KEY (id),
FOREIGN KEY(c_id) REFERENCES c (id)
);
INSERT INTO e VALUES(1,1,'e 1');
INSERT INTO e VALUES(2,2,'e 2');
Variante 1:
Code: Alles auswählen
all_a = session.query(A).all()
a = all_a[0]
print(a.value, a.b.value, a.c.e.value)
Setzt beim `all()` eine SQL-Abfrage ab um die `A`-Objekte zu laden, und jeweils eine Abfrage für jeden Attributzugriff:
Code: Alles auswählen
-- all()
SELECT a.id AS a_id, a.value AS a_value FROM a
-- a.b
SELECT b.id AS b_id, b.a_id AS b_a_id, b.value AS b_value
FROM b
WHERE ? = b.a_id
-- a.c
SELECT c.id AS c_id, c.a_id AS c_a_id, c.value AS c_value
FROM c
WHERE ? = c.a_id
-- c.e
SELECT e.id AS e_id, e.c_id AS e_c_id, e.value AS e_value
FROM e
WHERE ? = e.c_id
Variante 2:
Code: Alles auswählen
all_a = session.query(A).options(joinedload("*")).all()
a = all_a[0]
print(a.value, a.b.value, a.c.e.value)
Setzt *eine* SQL-Abfrage gleich beim `all()` ab:
Code: Alles auswählen
SELECT a.id AS a_id, a.value AS a_value, b_1.id AS b_1_id, b_1.a_id AS b_1_a_id,
b_1.value AS b_1_value, d_1.id AS d_1_id, d_1.b_id AS d_1_b_id,
d_1.value AS d_1_value, c_1.id AS c_1_id, c_1.a_id AS c_1_a_id,
c_1.value AS c_1_value, e_1.id AS e_1_id, e_1.c_id AS e_1_c_id,
e_1.value AS e_1_value
FROM a
LEFT OUTER JOIN b AS b_1 ON a.id = b_1.a_id
LEFT OUTER JOIN d AS d_1 ON b_1.id = d_1.b_id
LEFT OUTER JOIN c AS c_1 ON a.id = c_1.a_id
LEFT OUTER JOIN e AS e_1 ON c_1.id = e_1.c_id
Re: sqlalchemy-postgresql, join 5 tbl, f-key von einer in zwei
Verfasst: Mittwoch 14. April 2021, 12:22
von rascha
@__blackjack__ Hi! das funktioniert, ich hatte schon die relationships verwendet aber von allen 3 objecten in
form von session.query(a, b, c).options(joinload(a.b_relatin),joinload(a.c_relatin),joinload(b.d_relation),joinload(c.e_relation)).all()
es hat aber nur richtig funktioniert solange b und c die selben f-key's von a hatten sonst war es konflikt!
aber deine Methode session.query(A).options(joinedload("*")).all() habe ich probiert und kein Konflikt.
super herzlichen Dank! L.G