SQLAlchemy ORM如何将查询与表连接起来

Posted

技术标签:

【中文标题】SQLAlchemy ORM如何将查询与表连接起来【英文标题】:SQLAlchemy ORM how to join query with table 【发布时间】:2018-08-24 15:43:36 【问题描述】:

我在 SQLAlchemy 中有一个 ORM 模型,它存储了一些价格(按 product_id 和日期)和汇率(按 currency_from、currency_to 和 date)。我有一个返回查询对象的函数。该查询具有 id、日期、货币和价格列。或者,价格可以转换为另一种货币。我想将此查询对象作为参数并将其与ExRates 表连接,以转换为不同的货币。

我使用的解决方法是读取我需要的部分到pandas.DataFrame 并合并。另一个棘手的部分是,有时我有周六的价格,但没有 ex rate。在这种情况下,应使用最后可用的汇率。同样在pandas 中,我可以使用.reindex.fillna(method='ffill') 来实现它,但我想纯粹在SQL 中实现它。

以下是我的代码中的一些参考:

class Price(ReprMixin, GenFromDfMixin, ToDfMixin, Base):
    __tablename__ = 'prices'

    benchmark_id = Column(String, ForeignKey('benchmarks.benchmark_id'), index=True, primary_key=True)
    date = Column(Date, index=True, primary_key=True)
    price = Column(Float)
    return_ytd = Column(Float)

class Benchmark(ReprMixin, GenFromDfMixin, ToDfMixin, Base):
    __tablename__ = 'benchmarks'

    benchmark_id = Column(String, primary_key=True)
    index_name = Column(String)
    currency = Column(String)
    ...

class ExRate(ReprMixin, GenFromDfMixin, ToDfMixin, Base):
    __tablename__ = 'rates'

    cur_from = Column(String, primary_key=True)
    cur_to = Column(String, primary_key=True)
    date = Column(Date, primary_key=True, index=True)
    ex_rate = Column(Float)

def _query_by_id_and_date(benchmark_id, date_min=None, date_max=None):
    if date_min is None:
        date_min = datetime.date(1900, 1, 1)
    if date_max is None:
        date_max = datetime.date(2222, 1, 1)
    prices = dal.session.query(Price.benchmark_id, Price.date, Price.price, Benchmark.currency).join(Benchmark)\
        .filter(Price.benchmark_id == benchmark_id).filter(Price.date.between(date_min, date_max))
    return prices

def _currency_convert(q, to_curr):
    pass  
# I would like to call this function like this:
# _currency_convert(_query_by_id_and_date('some_id'), 'EUR')
# and get the same 4 column query, but with prices converted to a new currency

【问题讨论】:

使用货币过滤器创建 ExRate 表的子查询,并使用子查询加入您的价格表。 【参考方案1】:

我不确定我是否正确理解了您的问题。我认为您正在尝试根据不同的货币转换价格。试试看

from sqlalchemy import and_    
query=session.query(Price.benchmark_id,Price.date,Price.return_ytd,Price.price*ExRate.ex_rate)\
        .join(Benchmark)\
        .join(ExRate, ExRate.cur_from==Benchmark.currency)\
        .filter(and_(ExRate.cur_from==Benchmark.currency, ExRate.cur_to=='EUR')

【讨论】:

刚放假回来,今天试试。我已经看到了一个问题 - ex rate 也是按日期计算的,您的查询似乎没有考虑到它。我还将尝试您在评论中建议的子查询。 使用and_ 比链接.filter(...).filter(...) 有什么优势吗?

以上是关于SQLAlchemy ORM如何将查询与表连接起来的主要内容,如果未能解决你的问题,请参考以下文章

ORM SQLAlchemy 表于表的关系

如何在没有ORM的情况下使用SQLAlchemy查询从表中删除行?

如何将特定的 SQL 语句实现为 SQLAlchemy ORM 查询

SQLAlchemy(一):SQLAlchemy去连接数据库ORM介绍将ORM模型映射到数据库中

如何将 Sqlalchemy ORM 查询结果转换为包含关系的单个联接表?

SQLAlchemy 仅从连接表中选择列