在 SQLAlchemy 和 Postgres 中查询重叠的时间范围

Querying for overlapping time ranges in SQLAlchemy and Postgres

我正在使用 Flask-SQLAlchemy 来描述 Postgres 数据库。三个相关表如下所示(部分):

from sqlalchemy.dialects.postgresql import TSTZRANGE

class Shift(Base):
    __tablename__ = "shifts"

    id = db.Column(db.Integer, primary_key=True)
    hours = db.Column(TSTZRANGE, nullable=False)

class Volunteer(Base):
    __tablename__ = "volunteers"

    id = db.Column(db.Integer(), primary_key=True)

    shifts = db.relationship(
        "Shift",
        secondary="shift_assignments",
        backref=db.backref("volunteers", lazy="dynamic"),
    )

class ShiftAssignment(Base):
    __tablename__ = "shift_assignments"
    __table_args__ = (db.UniqueConstraint('shift_id', 'volunteer_id', name='_shift_vol_uc'),)

    id = db.Column(db.Integer, primary_key=True)
    shift_id = db.Column("shift_id", db.Integer(), db.ForeignKey("shifts.id"))
    volunteer_id = db.Column(
        "volunteer_id", db.Integer(), db.ForeignKey("volunteers.id")
    )

现在,我正在将 Volunteer 分配给新的 Shift,并希望确保该卷尚未同时提交给不同的 Shift

我已经在 Volunteer 实例方法中尝试过,但它不起作用:

new_shift = db.session.get(Shift, new_shift_id)

if new_shift not in self.shifts:
    for shift in self.shifts:
        overlap = db.session.scalar(shift.hours.overlaps(new_shift.hours))

这会导致以下异常:

'DateTimeTZRange' object has no attribute 'overlaps'

看来我什至不应该通过遍历列表来执行此操作,而应该直接查询数据库以执行日期重叠数学运算。所以我想我需要加入志愿者和班次,然后过滤以找出是否有任何班次与目标班次重叠。但我不知道该怎么做,overlaps 和它的 RangeOperators 朋友的例子实在太少了。

在此表示感谢。

这比我做的容易多了。同样,这是在 Volunteer 实例方法中。

new_shift = db.session.get(Shift, new_shift_id)

overlapping_shift = (
    db.session.query(Shift, ShiftAssignment)
    .join(ShiftAssignment)
    .filter(ShiftAssignment.volunteer_id == self.id)
    .filter(Shift.hours.overlaps(new_shift.hours))
    .first()
)

if overlapping_shift:
    print("overlap found")

注意查询returns一个(Shift, ShiftAssignment)元组。我们加入两个适当的表,然后过滤两次,留下任何重叠的班次分配给当前志愿者。