合并两个查询,sqlalchemy

mr_*_*thi 2 python sqlalchemy

我对 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)
    )
)
Run Code Online (Sandbox Code Playgroud)

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)
    )
)
Run Code Online (Sandbox Code Playgroud)

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

Ray*_*hns 5

假设UserSessionQuestionAnswer是两个user_id可以用作外键的表,您可以执行以下操作

query(UserSession).join(QuestionAnswer, UserSession.user_id = QuestionAnswer.user_id)
Run Code Online (Sandbox Code Playgroud)

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

也就是说,您需要检查一些复杂的内容,执行两个查询并将它们连接起来可能比使用复杂的子查询更有意义。或者,做联合可能是最有意义的!

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

参考


van*_*van 5

简单的子查询应该可以解决问题:

q = session.query(user_logins_count.subquery(), user_questions_count.subquery())
logins_count, questions_count = q.first()
Run Code Online (Sandbox Code Playgroud)

检索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")
        )
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

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