【问题标题】:Combine two queries, sqlalchemy结合两个查询,sqlalchemy
【发布时间】:2020-10-24 04:28:33
【问题描述】:

我对sqlalchemy(以及sql)真的很陌生,所以请不要拍。

我有两个疑问:

user_logins_count = self.request.db.query(
    sa.func.count(UserSession.id)
).filter(
    sa.and_(
        UserSession.user_id == user_id,
        sa.between(UserSession.date_login_session, start_date, end_date)
    )
)

user_questions_count = self.request.db.query(
    sa.func.count(QuestionAnswer.id).label('questions_amount')
).filter(
    sa.and_(
        QuestionAnswer.user_id == user_id,
        sa.between(QuestionAnswer.created, start_date, end_date)
    )
)

是否可以有一个查询而不是这两个?

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    简单的subquery 应该可以解决问题:

    q = session.query(user_logins_count.subquery(), user_questions_count.subquery())
    logins_count, questions_count = q.first()
    

    在检索User 实例本身时,同时获取信息的另一种方法是使用hybrid_method

    class User(Base):
        __tablename__ = "user"
    
        id = Column(Integer, primary_key=True)
        name = Column(String(255))
    
        @hybrid_method
        def user_logins_count(self, start_date: datetime, end_date: datetime):
            return len(
                [
                    _login
                    for _login in self.sessions
                    if start_date <= _login.date_login_session <= end_date
                ]
            )
    
        @classmethod
        @user_logins_count.expression
        def user_logins_count_(cls, start_date: datetime, end_date: datetime):
            return (
                select([func.count(UserSession.id).label("user_logins_count")])
                .where(UserSession.user_id == cls.id)
                .where(UserSession.date_login_session >= start_date)
                .where(UserSession.date_login_session <= end_date)
                .group_by(UserSession.user_id)
                .label("user_logins_count")
            )
    

    在这种情况下,可以执行以下查询:

    res = session.query(User, User.user_logins_count(start_date, end_date)).filter(
        User.id == user_id
    )
    user, logins_count = res.first()
    print(user)
    print(logins_count)
    

    添加questions_count 可以用同样的方式完成。

    【讨论】:

      【解决方案2】:

      假设UserSessionQuestionAnswer 是两个表,其中user_id 可以用作foreign key,你可以这样做

      query(UserSession).join(QuestionAnswer, UserSession.user_id = QuestionAnswer.user_id)
      

      加入表格。如果您有一个联接,那么您可以更轻松地将它们作为一个单元进行查询,假设它们都具有您需要的日期信息。

      也就是说,您有一些复杂的东西要检查,执行两个查询并将它们连接起来可能比拥有一个复杂的子查询更有意义。或者,做一个union 可能是最有意义的!

      如果您发布您的数据结构,我可以更具体地帮助您构建一个可以执行您想做的事情的查询。这绝对是可能的,但它可能会有点棘手,因此查看您正在使用的数据示例和您构建的数据模型(作为 QuestionAnswer 和 UserSession 表基础的类)将非常有帮助。

      参考文献

      【讨论】:

      • 基于连接的解决方案有些令人不快的问题是需要广泛处理子表中没有行或没有符合条件的行的情况。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多