2016-03-29 8 views
0

Ich versuche, einen Join auf einer Tabelle durchzuführen, die zwei Foriegn-Schlüssel für dieselbe Tabelle hat. Nämlich SourceToOutputRelation zeigt zweimal auf Einträge, wie im Code gezeigt. Außerdem haben Einträge Tags. Ich versuche einen Join zu machen, so dass ich jede sourceToOutputRelation bekomme, die alle gegebenen Tags hat (via Entries). Ich versuche nur die Verbindung zu verstehen (die Filterung funktioniert, denke ich). Hier ist der Code, den ich für den Join und Filter habe. :sqlalchemy Join zu einer Tabelle über zwei Fremdschlüssel zu derselben Tabelle (mehrdeutiger Spaltenfehler)

''' 
    tags is a list of strings that are supposed to match the Tags.tag strings 
''' 
    from sqlalchemy.orm import aliased 


    q = SourceToOutputRelation.query.\ 
     join(Entries.source_entries, Entries.output_entries).\ 
     join(original_tag_registration).\ 
     join(Tags).\ 
     filter(Tags.tag == tags[0]) 
    print(q.all()) 

Hier meine Modelldefinitionen sind:

class SourceToOutputRelation(alchemyDB.Model): 

    __tablename__ = 'sourceToOutputRel' 
    id = alchemyDB.Column(alchemyDB.Integer, primary_key = True) 
    source_article = alchemyDB.Column(alchemyDB.Integer, alchemyDB.ForeignKey('entries.id')) 
    output_article = alchemyDB.Column(alchemyDB.Integer, alchemyDB.ForeignKey('entries.id')) 

class Entries(alchemyDB.Model): 

    __tablename__ = 'entries' 
    id = alchemyDB.Column(alchemyDB.Integer, primary_key = True)  
    tags = alchemyDB.relationship('Tags', 
           secondary = original_tag_registration, 
           backref = alchemyDB.backref('relevant_entries', lazy = 'dynamic'), 
           lazy = 'dynamic')  
    source_entries = alchemyDB.relationship('SourceToOutputRelation', 
              primaryjoin="SourceToOutputRelation.output_article==Entries.id", 
              foreign_keys = [SourceToOutputRelation.output_article], 
              backref = alchemyDB.backref('output', lazy = 'joined'), 
              lazy = 'dynamic', 
              cascade = 'all, delete-orphan') 
    output_entries = alchemyDB.relationship('SourceToOutputRelation',            
              primaryjoin="SourceToOutputRelation.source_article==Entries.id", 
              foreign_keys = [SourceToOutputRelation.source_article], 
              backref = alchemyDB.backref('source', lazy = 'joined'), 
              lazy = 'dynamic', 
              cascade = 'all, delete-orphan') 



original_tag_registration = alchemyDB.Table('original_tag_registration', 
    alchemyDB.Column('tag_id', alchemyDB.Integer, alchemyDB.ForeignKey('tagTable.id')), 
    alchemyDB.Column('entry_id', alchemyDB.Integer, alchemyDB.ForeignKey('entries.id')) 
    ) 


class Tags(alchemyDB.Model): 
    ''' 
     a table to hold unique tags 
    ''' 
    __tablename__ = 'tagTable' 
    id = alchemyDB.Column(alchemyDB.Integer, primary_key = True) 
    tag = alchemyDB.Column(alchemyDB.String(64), unique=True) 
    entries_with_this_tag = alchemyDB.relationship('Entries', 
               secondary = original_tag_registration, 
               backref = alchemyDB.backref('tag', lazy = 'dynamic'), 
               lazy = 'dynamic') 

ich diesen Fehler:

OperationalError: (OperationalError) ambiguous column name: sourceToOutputRel.id u'SELECT "sourceToOutputRel".id AS "sourceToOutputRel_id", "sourceToOutputRel".source_article AS "sourceToOutputRel_source_article", "sourceToOutputRel".output_article AS "sourceToOutputRel_output_article", "sourceToOutputRel".needs_processing AS "sourceToOutputRel_needs_processing", "sourceToOutputRel".number_of_votes AS "sourceToOutputRel_number_of_votes", "sourceToOutputRel".date_related AS "sourceToOutputRel_date_related", "sourceToOutputRel".confirmed_relationship_type AS "sourceToOutputRel_confirmed_relationship_type", entries_1.id AS entries_1_id, entries_1.title AS entries_1_title, entries_1.text AS entries_1_text, entries_1.body_html AS entries_1_body_html, entries_1.user_id AS entries_1_user_id, entries_1.date_posted AS entries_1_date_posted, entries_2.id AS entries_2_id, entries_2.title AS entries_2_title, entries_2.text AS entries_2_text, entries_2.body_html AS entries_2_body_html, entries_2.user_id AS entries_2_user_id, entries_2.date_posted AS entries_2_date_posted \nFROM entries JOIN "sourceToOutputRel" ON "sourceToOutputRel".output_article = entries.id JOIN "sourceToOutputRel" ON "sourceToOutputRel".source_article = entries.id JOIN original_tag_registration ON entries.id = original_tag_registration.entry_id JOIN "tagTable" ON "tagTable".id = original_tag_registration.tag_id LEFT OUTER JOIN entries AS entries_1 ON "sourceToOutputRel".output_article = entries_1.id LEFT OUTER JOIN entries AS entries_2 ON "sourceToOutputRel".source_article = entries_2.id \nWHERE "tagTable".tag = ?' (u'brods',)

+0

Welche SQL soll SQLAlchemy ausgeben? – univerio

+0

Ich weiß es nicht. Ich hoffe, ich habe erklärt, was die Abfrage zurückgeben soll: alle SourceToOutput-Objekte, die Tags in der Tag-Liste haben. – user442920

+0

Wenn Sie nicht wissen, welche SQL Sie SQLAlchemy ausgeben möchten, wie hoffen Sie, die richtige SQLAlchemy-Beschwörung zu schreiben, um Ihnen zu geben, was Sie wollen? SQLAlchemy ist kein Ersatz für das Erlernen oder Kennen von SQL. – univerio

Antwort

1

Blick auf die docs. Ziffer

Joins to a Target with an ON Clause

a_alias = aliased(Address) 

q = session.query(User).\ 
    join(User.addresses).\ 
    join(a_alias, User.addresses).\ 
    filter(Address.email_address=='[email protected]').\ 
    filter(a_alias.email_address=='[email protected]') 

Es gibt auf einem Tisch mehrere beitreten. Sie importieren bereits eine Alias-Funktion. Versuchen Sie diesen Code

''' 
    tags is a list of strings that are supposed to match the Tags.tag strings 
''' 
from sqlalchemy.orm import aliased 

entry_alias = aliased(Entries) 
q = SourceToOutputRelation.query.\ 
    join(Entries.source_entries).\ 
    join(entry_alias, Entries.output_entries).\ 
    join(original_tag_registration).\ 
    join(Tags).\ 
    filter(Tags.tag == tags[0]) 
print(q.all()) 
Verwandte Themen