【问题标题】:Querying for overlapping time ranges in SQLAlchemy and Postgres在 SQLAlchemy 和 Postgres 中查询重叠的时间范围
【发布时间】:2021-06-08 20:57:00
【问题描述】:

我正在使用 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,并希望确保该 vol 尚未同时提交给不同的 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 朋友的例子真的很少见。

非常感谢您的帮助。

【问题讨论】:

    标签: postgresql sqlalchemy flask-sqlalchemy


    【解决方案1】:

    这比我做的要容易得多。同样,这是在 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")
    

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

    【讨论】:

      猜你喜欢
      • 2019-03-19
      • 2020-04-21
      • 1970-01-01
      • 1970-01-01
      • 2012-12-09
      • 1970-01-01
      • 1970-01-01
      • 2012-01-18
      • 1970-01-01
      相关资源
      最近更新 更多