2016-03-23 40 views
0

我有一個表,dna_extraction_protocols其中包含有關DNA提取協議的數據。 incubations表中存儲的Incubation個對象佔用了多個鍵。孵化有一個duration_unit鍵,其中包含MeasurementUnit對象,該對象包含在measurement_units表中。在SQLAlchemy中加入相關表的相關表

這些表創建像這樣:

class DNAExtractionProtocol(Protocol): 
    __tablename__ = 'dna_extraction_protocols' 
    __mapper_args__ = {'polymorphic_identity': 'dna_extraction'} 
    id = Column(Integer, ForeignKey('protocols.id'), primary_key=True) 
    sample_mass = Column(Float) 
    mass_unit_id = Column(String, ForeignKey('measurement_units.id')) 
    mass_unit = relationship("MeasurementUnit", foreign_keys=[mass_unit_id]) 
    digestion_buffer_id = Column(String, ForeignKey("solutions.id")) 
    digestion_buffer = relationship("Solution", foreign_keys=[digestion_buffer_id]) 
    digestion_buffer_volume = Column(Float) 
    digestion_id = Column(Integer, ForeignKey("incubations.id")) 
    digestion = relationship("Incubation", foreign_keys=[digestion_id]) 
    lysis_buffer_id = Column(String, ForeignKey("solutions.id")) 
    lysis_buffer = relationship("Solution", foreign_keys=[lysis_buffer_id]) 
    lysis_buffer_volume = Column(Float) 
    lysis_id = Column(Integer, ForeignKey("incubations.id")) 
    lysis = relationship("Incubation", foreign_keys=[lysis_id]) 
    proteinase_id = Column(String, ForeignKey("solutions.id")) 
    proteinase = relationship("Solution", foreign_keys=[proteinase_id]) 
    proteinase_volume = Column(Float) 
    inactivation_id = Column(Integer, ForeignKey("incubations.id")) 
    inactivation = relationship("Incubation", foreign_keys=[inactivation_id]) 
    cooling_id = Column(Integer, ForeignKey("incubations.id")) 
    cooling = relationship("Incubation", foreign_keys=[cooling_id]) 
    centrifugation_id = Column(Integer, ForeignKey("incubations.id")) 
    centrifugation = relationship("Incubation", foreign_keys=[centrifugation_id]) 

    volume_unit_id = Column(String, ForeignKey('measurement_units.id')) 
    volume_unit = relationship("MeasurementUnit", foreign_keys=[volume_unit_id]) 

class Incubation(Base): 
    __tablename__ = "incubations" 
    id = Column(Integer, primary_key=True) 
    speed = Column(Float) 
    duration = Column(Float) 
    temperature = Column(Float) 
    movement = Column(String) # "centrifuge" or "shake" 

    #speed - usually in RPM - will refer to either centrifugation or shaking (See above) 
    speed_unit_id = Column(String, ForeignKey('measurement_units.id')) 
    speed_unit = relationship("MeasurementUnit", foreign_keys=[speed_unit_id]) 
    duration_unit_id = Column(String, ForeignKey('measurement_units.id')) 
    duration_unit = relationship("MeasurementUnit", foreign_keys=[duration_unit_id]) 
    temperature_unit_id = Column(String, ForeignKey('measurement_units.id')) 
    temperature_unit = relationship("MeasurementUnit", foreign_keys=[temperature_unit_id] 

class MeasurementUnit(Base): 
    __tablename__ = "measurement_units" 
    id = Column(Integer, primary_key=True) 
    code = Column(String, unique=True) 
    long_name = Column(String) 
    siunitx = Column(String) 

現在,我想提取大熊貓據幀,在那裏我能得到DNAPurificationProtocol對象的所有屬性的鏈接Incubation的對象,以及一鏈接MeasurementUnit對象。

我已經嘗試了多種方法,而這一次似乎很好地爲第一種關係的工作:

sql_query = session.query(DNAExtractionProtocol, MeasurementUnit, Incubation) \ 
    .join(MeasurementUnit, MeasurementUnit.id == DNAExtractionProtocol.volume_unit_id) \ 
    .join(Incubation, Incubation.id == DNAExtractionProtocol.lysis_id) \ 
    .filter(tables[table].code == code) 

但是我覺得自己像一個合乎邏輯的延伸:

sql_query = session.query(DNAExtractionProtocol, MeasurementUnit, Incubation) \ 
    .join(MeasurementUnit, MeasurementUnit.id == DNAExtractionProtocol.volume_unit_id) \ 
    .join(Incubation, Incubation.id == DNAExtractionProtocol.lysis_id) \ 
    .join(MeasurementUnit, MeasurementUnit.id == Incubation.temperature_unit_id) \ 
    .filter(tables[table].code == code) 

與失敗:

sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) ambiguous column name: measurement_units.id [SQL: u'SELECT protocols.type, dna_extraction_protocols.id, protocols.id, protocols.code, protocols.name, dna_extraction_protocols.sample_mass, dna_extraction_protocols.mass_unit_id, dna_extraction_protocols.digestion_buffer_id, dna_extraction_protocols.digestion_buffer_volume, dna_extraction_protocols.digestion_id, dna_extraction_protocols.lysis_buffer_id, dna_extraction_protocols.lysis_buffer_volume, dna_extraction_protocols.lysis_id, dna_extraction_protocols.proteinase_id, dna_extraction_protocols.proteinase_volume, dna_extraction_protocols.inactivation_id, dna_extraction_protocols.cooling_id, dna_extraction_protocols.centrifugation_id, dna_extraction_protocols.volume_unit_id, measurement_units.id, measurement_units.code, measurement_units.long_name, measurement_units.siunitx, incubations.id, incubations.speed, incubations.duration, incubations.temperature, incubations.movement, incubations.speed_unit_id, incubations.duration_unit_id, incubations.temperature_unit_id \nFROM protocols JOIN dna_extraction_protocols ON protocols.id = dna_extraction_protocols.id JOIN measurement_units ON measurement_units.id = dna_extraction_protocols.volume_unit_id JOIN incubations ON incubations.id = dna_extraction_protocols.lysis_id JOIN measurement_units ON measurement_units.id = incubations.temperature_unit_id \nWHERE protocols.code = ?'] [parameters: ('EPDqEP',)]

任何想法如何否則我可以得到我在找什麼?

回答

1

問題的核心在於你加入同一張表兩次。在SQL-土地,你解決這個問題的辦法是別名其中之一:

SELECT * FROM protocols 
JOIN dna_extraction_protocols ON ... 
JOIN measurement_units ON ... 
JOIN incubations ON ... 
JOIN measurement_units AS incubation_measurement_units ON incubation_measurement_units.id = incubations.temperature_unit_id 

同樣的事情在這裏:

sql_query = session.query(DNAExtractionProtocol, MeasurementUnit, Incubation) \ 
    .join(MeasurementUnit, ...) \ 
    .join(Incubation, ...) \ 
    .join(MeasurementUnit, ..., aliased=True) \ 
    .filter(tables[table].code == code) 

如果你需要從返回列或過濾的別名的表,你會遇到問題,因爲你們無法消除這兩者之間的歧義。在這種情況下,您需要加入一個明確的aliased()結構。

IncubationMeasurementUnit = aliased(MeasurementUnit) 
sql_query = session.query(DNAExtractionProtocol, MeasurementUnit, Incubation, IncubationMeasurementUnit) \ 
    .join(MeasurementUnit, ...) \ 
    .join(Incubation, ...) \ 
    .join(IncubationMeasurementUnit, ...) \ 
    .filter(tables[table].code == code) 
+0

我媽嘗試使用此[這裏](https://github.com/TheChymera/medab​​a/blob/ef69d57dbafa34a4d83402acc5aaba6f1a043c89/src/dbdata/fmri.py#L41-L46),但這不檢索來自'incubations'條目鏈接的'measurement_units'條目的列。事實上,我有相同數量的列有或沒有最後的連接。任何想法有什麼不對? – TheChymera

+1

@TheChymera你沒有完全複製這個例子。您在查詢的實體列表中缺少「IncubationMeasurementUnit」。 – univerio