简体   繁体   中英

Python/SQLAlchemy - Need to convert an inner join query with 3 tables into Python

I need some help converting this query into SQLAlchemy.

select field from table t1 join table t2 on t1.detail_id = t2.id join table t3 on t3.id = t2.rate_id where t2.name = 'fred' and t3.rate_type = 'Custom' and t3.description = 'Default';

I have been able to convert inner join queries with two tables, but need some help with this one.

Appreciate your help.TIA.

If simple SQL query is enough you can try:

session.execute("SELECT t1.field AS t1_field "
    "FROM t1 JOIN t2 ON t1.detail_id = t2.id JOIN t3 ON t2.rate_id = t3.id "
    "WHERE t2.name = :name AND t3.rate_type = :rate_type AND t3.description = :description",
    {'name': 'fred', 'rate_type': 'Custom', 'description': 'Default'})

But if you want to use SQLAlchemy declarative base then the query would look like:

results = session.query(T1.field).join(T2, T1.detail_id == T2.id).join(T3, T2.rate_id == T3.id).\
    filter(T2.name == 'fred').\
    filter(T3.rate_type == 'custom').\
    filter(T3.description == 'lorem ipsum').all()

For the following models:

from sqlalchemy import create_engine, Integer, ForeignKey, String, Column
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class T1(Base):
    __tablename__ = 't1'
    id = Column(Integer, primary_key=True)
    field = Column(String)
    detail_id = Column(Integer, ForeignKey("t1.id"))


class T2(Base):
    __tablename__ = 't2'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    rate_id = Column(Integer, ForeignKey("t1.id"))


class T3(Base):
    __tablename__ = 't3'
    id = Column(Integer, primary_key=True)
    rate_type = Column(String)
    description = Column(String)

I hope it helps.

SQLAlchemy provide both ORM way and SQL way to operate database. You can use exactly the raw SQL language (or SQLAlachemy SQL Express) to query.

(1) RAW SQL QUERY,Sample code:

engine = create_engine(...)
q = 'SELECT foo FROM t_bar WHERE col_name=:v_parameters'
rs = engine.execute(sqlalchemy.text(q), v_parameters=your_actual_value)

Check execute and basic usage . Also take look at ResultProxy to understand how to operate on returned result.

(2) ORM. If you want to use ORM, firstly you have to define models and mapper class. Sample Code.

from sqlalchemy import Column, ForeignKey
from sqlalchemy.types import String, Integer
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base


Base = declarative_base()


class Father(Base):
    id = Column(Integer, primary_key=True)
    name = Column(String(31), unique=True, nullable=False)
    # Relationship attributes
    children = relationship('Sons',
                            passive_deletes=True,
                            back_populates='father')


class Son(Base):
    id = Column(Integer, primary_key=True)
    name = Column(String(31), unique=True, nullable=False)
    # foreign keys
    p_id = Column(Integer, ForeignKey('Father.id',
                                      ondelete='CASCADE',
                                      onupdate='CASCADE'))
    # Relationship attributes
    parent = relationship('Father',
                          passive_deletes=True,
                          back_populates='sons')

Then you can do ORM query operations

session.query(Father).join(Father.sons).filter(Son.name=='Sam')

is equal to SQL query

SELECT father.id, father.name FROM father JOIN son ON father.id=son.p_id WHERE son.name='Sam'.

Please check ORM mapper and ORM Query for more information.

For you application. If you have well mapped all of your tables, then you can use ORM way. If you do not need ORM feature, you can just use RAW SQL query.

Thank.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM