我得到了这个多对多的设计

class Parent(Base):
    __tablename__ = "parent"
    id = Column(Integer, primary_key=True)
    parent_number = Column(String)
    start_date = Column(DateTime, primary_key=True)
    end_date = Column(DateTime)
    children= relationship("Child", lazy="selectin")


class Child(Base):
    __tablename__ = "child"
    id = Column(Integer, primary_key=True)
    start_date = Column(DateTime, primary_key=True)
    end_date = Column(DateTime)
    parent_id = Column(Integer, ForeignKey("parent.id"))

这两个模型都有一个start_dateend_date来注册每一行的有效日期范围,从而产生一个复合主键.

我想要做的是能够构造满足start_dateend_date上的条件的Parent对象以及子array.

我try 了一个简单的查询,比如

session.query(Parent)
.filter(Parent.parent_number == '1234')
.filter(Parent.start_date > given_date & Parent.end_date < given_date)

这会导致两个查询

SELECT *
FROM Parent
WHERE parent_number = '1234' AND start_date > '2024-02-14' AND end_date < '2024-02-14'
 
SELECT Parent.id, Parent.start_date, Child.*
FROM Parent
JOIN Child ON Child.parent_id = Parent.id
WHERE (Parent.id, Parent.start_date) IN ((id_of_previous_parent, start_date_of_previous_parent))

第一个查询很好,但对于第二个查询,我希望类似于

SELECT Parent.id, Parent.start_date, Child.*
FROM Parent
JOIN Child ON Child.parent_id = Parent.id
WHERE (Parent.id, Parent.start_date) IN ((id_of_previous_parent, start_date_of_previous_parent)) AND Child.start_date > '2024-02-14' AND Child.end_date < '2024-02-14'

我试过这个天真的问题

session.query(Parent)
.filter(Parent.parent_number == '1234')
.filter(Parent.start_date > given_date & Parent.end_date < given_date)
.filter(Child.start_date > given_date & Child.end_date < given_date)

但它只改变了第一个查询.

我还try 加入如下查询

session.query(Parent)
.join(Child)
.filter(Parent.parent_number == '1234')
.filter(Parent.start_date > given_date & Parent.end_date < given_date)
.filter(Child.start_date > given_date & Child.end_date < given_date)

没有结果.

推荐答案

您可以使用criteria in loader options过滤返回的相关对象.

在这种情况下,这样的条件将仅包括从开始日期到结束日期范围内的子项.

orm.selectinload(
    Parent.children.and_(
         Child.start_date == start_date, Child.end_date <= end_date
    )
)

完整的查询如下所示:

import sqlalchemy as sa
from sqlalchemy import orm

query = (
    session.query(Parent)
    .filter(sa.and_(Parent.start_date >= start_date, Parent.end_date <= end_date))
    .options(
        orm.selectinload(
            Parent.children.and_(
                Child.start_date == start_date, Child.end_date <= end_date
            )
        )
    )
)

使用2.0样式的代码时,语法是相同的:

q = (
    sa.select(Parent)
    .where(sa.and_(Parent.start_date >= start_date, Parent.end_date <= end_date))
    .options(
        orm.selectinload(
            Parent.children.and_(
                Child.start_date == start_date, Child.end_date <= end_date
            )
        )
    )
)

Python相关问答推荐

如何让 turtle 通过点击和拖动来绘制?

抓取rotowire MLB球员新闻并使用Python形成表格

运行Python脚本时,用作命令行参数的SON文本

如果值不存在,列表理解返回列表

ODE集成中如何终止solve_ivp的无限运行

如果条件不满足,我如何获得掩码的第一个索引并获得None?

如何在WSL2中更新Python到最新版本(3.12.2)?

如何设置视频语言时上传到YouTube与Python API客户端

部分视图的DataFrame

当递归函数的返回值未绑定到变量时,非局部变量不更新:

Beautifulsoup:遍历一个列表,从a到z,并解析数据,以便将其存储在pdf中.

来自Airflow Connection的额外参数

如何从数据框列中提取特定部分并将该值填充到其他列中?

正在try 让Python读取特定的CSV文件

在任何要保留的字段中添加引号的文件,就像在Pandas 中一样

如何在Pandas中用迭代器求一个序列的平均值?

FileNotFoundError:[WinError 2]系统找不到指定的文件:在os.listdir中查找扩展名

迭代工具组合不会输出大于3的序列

关于数字S种子序列内部工作原理的困惑

在不降低分辨率的情况下绘制一组数据点的最外轮廓