2017-09-07 3 views
0

Ich habe Probleme, diese SQL-Abfrage in eine SQL-Abfrage Alchemy Umwandlung:SQL Alchemy Join-Anweisung

query = """ 
      SELECT i.case_num, 
        to_char(i.date_time, 'FMMonth FMDD, YYYY'), 
        to_char(i.date_time, 'HH24:MI'), 
        i.incident_type, 
        i.incident_cat, 
        i.injury, 
        i.property_damage, 
        i.description, 
        i.root_cause, 
        a.corrective_action, 
        a.due_date, 
        i.user_id 
       FROM incident as i, action_items as a 
       WHERE i.case_num = a.case_id AND i.case_num = %s; 
      """ 

Ich habe versucht, die folgenden aber haben nichts als Fehler erhalten:

sqlalchemy.orm.exc .NoResultFound: Es wurde keine Zeile für einen() gefunden

results = dbsession.query(Incidents.case_num, 
            func.to_char(Incidents.date_time, 'FMMonth FMDD, YYYY'), 
            func.to_char(Incidents.date_time, 'HH24:MI'), 
            Incidents.incident_type, 
            Incidents.incident_cat, 
            Incidents.injury, 
            Incidents.property_damage, 
            Incidents.description, 
            Incidents.root_cause, 
            Actions.corrective_action, 
            Actions.due_date, 

Incidents.user_id).join(Actions).filter_by(case_id = id).one() 

Attribute: Mapper

results = dbsession.query(Incidents.case_num, 
           func.to_char(Incidents.date_time, 'FMMonth FMDD, YYYY'), 
           func.to_char(Incidents.date_time, 'HH24:MI'), 
           Incidents.incident_type, 
           Incidents.incident_cat, 
           Incidents.injury, 
           Incidents.property_damage, 
           Incidents.description, 
           Incidents.root_cause, 
           Incidents.user_id).join(Actions.corrective_action, Actions.due_date).filter_by(case_id = id).one() 

Ich glaube, ich kann zwei separate Abfragen durchführen, würde aber lieber herausfinden, wie man eine Join-Abfrage durchführt.

+0

Was angezeigt wird, wenn Sie Zeichenfolge Darstellung von Ihnen drucken r Frage (sagen wir, die erste)? – erhesto

+0

Nichts, also glaube ich nicht, dass die Abfrage richtig formatiert ist. – JTP709

+0

Was meinst du mit nichts? Wird das Drucken durch eine Ausnahme unterbrochen oder ist das Ergebnis eine leere Zeichenfolge? – erhesto

Antwort

1

Sie sollten keinen Join explizit angeben müssen, damit sqlalchemy die gewünschte Anweisung generiert.

Auch (meiner Meinung nach). Vermeiden Sie die Verwendung von filter_by.

In diesem Fall ist filter_by nicht intelligent genug, um zu erkennen, dass id eine Spalte in Incidents ist, weil id eine eingebaute Funktion ist. filter_by(see source) akzeptiert, wo Bedingungen als Schlüsselwort Argumente, entpackt sie, behandelt die Schlüssel als Spalten nachgeschlagen werden, , aber nicht die Werte, dann ruft es die filter Methode mit allen Bedingungen verbunden.

relevant Stück Code:

def filter_by(self, **kwargs): 
    clauses = [_entity_descriptor(self._joinpoint_zero(), key) == value 
       for key, value in kwargs.items()] 
    return self.filter(sql.and_(*clauses)) 

wenn id wurde als linker Wert zur Verfügung gestellt, das heißt

stmt = dbsession.query(...).join(...).filter_by(id = 123) 

Die Aussage zusammenstellen würde.Allerdings würde die folgende nicht

stmt = dbsession.query(...).join(...).filter_by(id = case_id) 

kompiliert, da ist case_id keine Variable in Umfang

Und die Version des OP

stmt = dbsession.query(...).join(...).filter_by(case_id = id) 

case_id richtig lösen können, und sieht, dass es etwas im aktuellen Bereich namens id (das eingebaute) gibt, und versucht zu verwenden Dieses es

sollte tun, was Sie wollen:

results = dbsession.query(
    Incidents.case_num, 
    func.to_char(Incidents.date_time, 'FMMonth FMDD, YYYY'), 
    func.to_char(Incidents.date_time, 'HH24:MI'), 
    Incidents.incident_type, 
    Incidents.incident_cat, 
    Incidents.injury, 
    Incidents.property_damage, 
    Incidents.description, 
    Incidents.root_cause, 
    Actions.corrective_action, 
    Actions.due_date, 
    Incidents.user_id).filter(
    Actions.case_id == Incidents.id 
).filter(
    Incidents.case_num == 123 
).one() 
#^here's how one would add multiple filters to a query 

FYI, können Sie query Objekte speichern und überprüfen sie, wie folgt aus:

stmt = dbsession.query(...).filter(...) 
print(stmt) 

und dann die Ergebnisse holen mit

stmt.one() 
# or stmt.first() or stmt.all() or ... 
+0

Während ich Ihre Meinung teile, dass das expliziter 'filter()' in vielen Situationen schöner ist, ist die Argumentation hier nicht stichhaltig. Das angegebene Beispiel zeigt nicht, was "id" in ihrem Fall ist. Es könnte sogar die eingebaute Funktion sein, wie Sie vermutet haben. Zu sagen, dass "filter_by" nicht schlau genug ist zu erkennen, dass "id" eine Spalte in "Incidents" ist, fordert sie möglicherweise auf, das Unmögliche zu tun. Stattdessen würde es helfen zu erklären, wie 'filter_by()' tatsächlich funktioniert. –

+0

Danke @ IljaEverilä, sobald ich eine Chance bekomme, werde ich meine Antwort aktualisieren und erklären, wie 'filter_by' funktioniert. Ich denke, es hat etwas mit variadischen Argumenten zu tun, aber ich muss mir die Quelle ansehen, bevor ich meine Antwort aktualisiere. –

+0

[Die Dokumente sind eigentlich ziemlich anständig] (http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.query.Query.filter_by). 'filter_by()' verwendet die angegebenen Schlüsselwortargumente und "Die Schlüsselwortausdrücke werden aus der primären Entität der Abfrage oder der letzten Entität extrahiert, die das Ziel eines Aufrufs von' Query.join() 'war." Da also die primäre Entität oder ein vorheriges Ziel für einen Join X ist, ist ein 'filter_by (y = z)' äquivalent zu 'filter (Xy == z) '(+' und_' verschiedene Kriterien usw.). . Und wiederum bevorzuge ich eigentlich 'filter()' die meiste Zeit. –

Verwandte Themen