2

我是烧瓶和 ORM 的新手,我正在为我的学习编写一个示例应用程序。

我有这个模型:

class Timesheet(Base):
    __tablename__ = 'Timesheet'

    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey('user.id'), nullable='False')
    start_date = Column(Date, nullable=False)
    end_date = Column(Date, nullable=False)
    total_time = Column(String(), nullable=False)

每个用户都需要每周提交他的时间表,如果他错过了任何时间表,我们需要报告时间表。

例如user1时间表是这样的

Start_date | end_date
---------------------
2013-07-01 | 2013-07-08 
2013-07-08 | 2013-07-15
2013-07-22 | 2013-07-29

我们需要报告错过的 ( 2013-07-15 | 2013-07-22) 时间表

如何查询以在 sqlalchemy 中获得此结果?

4

3 回答 3

3

The problem you are facing is known by the name gaps and islands in SQL world. You can google it (there's plenty of information on this topic) or download for free chapter 5 from SQL Server MVP Deep Dives book which is dedicated to this problem. Adapted first gaps example from this chapter to SQLAlachemy follows:

t1 = aliased(Timesheet)
t2 = aliased(Timesheet)

subq1 = session.query(
    func.min(t2.start_date)
).filter(
    (t2.start_date > t1.end_date) &
    (t2.user_id == t1.user_id)
).correlate(t1).as_scalar()

subq2 = session.query(t2).filter(
    (t2.start_date == t1.end_date) &
    (t2.user_id == t1.user_id)
).correlate(t1)

subq3 = session.query(
    func.max(t2.start_date)
).filter(
    t2.user_id == t1.user_id
).correlate(t1)

print session.query(
    t1.user_id,
    t1.end_date.label('start_date'),
    subq1.label('end_date')
).filter(
    (~subq2.exists()) &
    (t1.end_date < subq3)
).all()
于 2013-07-14T21:11:59.617 回答
1

SQL 查询只能查找数据库中的数据,而不能查找丢失的数据,因此要有效地定位丢失的时间段,您需要对数据库进行一些重组。

我的建议是您在表格中预先填写数据。它或多或少会像这样工作:

  • 在开始输入最后一周的时间表之前,您运行一个脚本,为该周的所有用户添加一个空白时间表。该脚本将添加时间表条目,例如,将total_time字段设置为空。(顺便说一句,我注意到这个字段是一个字符串,不应该是一个整数吗?)。

  • 接下来,您输入您从用户那里收到的时间表。这基本上只会total_time用实际值更新空字段,因为脚本已经创建了所有时间表的记录。

  • 现在,您可以通过查找空total_time字段并打印这些记录的开始/结束日期的简单查询找到丢失的时间表,如果字段上有索引,SQL 可以非常有效地执行此操作total_time

于 2013-07-14T17:12:20.353 回答
1

我会再创建一张表:将记录过去和未来所有周的周数。

Weeks:
    id
    start_time
    end_time

然后我应该编写一个查询,将 Timesheet 与 Weeks 表正确连接,并按 Timesheet.start_dat 为空进行过滤。在这种情况下,您可能希望在开始日期和结束日期列上有索引。

顺便说一句,所有用户在同一日历周的开始和结束日期是否相同?如果是 - 我将规范化数据库并添加 Timesheet.week_id。

于 2013-07-14T17:38:33.730 回答