【问题标题】:Filtering join relationship with sqlalchemy使用 sqlalchemy 过滤连接关系
【发布时间】:2018-02-11 21:10:21
【问题描述】:

我正在使用 sqlalchemy 编写查询,但我觉得我在做的事情不是应该做的:我得到的查询太复杂了,所以我认为这不是应该的方式使用数据库/orm。

这是我的架构的简化版本:

class User(Base):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    longs = db.relationship('Login', backref='users')

class Login(Base):
    __tablename__ = 'logins'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    browser = db.Column(db.String(64)

对于给定的状态,我想拥有 A 中的所有元素,使得 B 中引用 A 的行数小于某个数量,假设是 5。

对于一个真实的案例,想象一下: A是用户列表 B是登录列表:

我想要所有使用 Firefox 登录少于 5 次的用户的列表)。这也包括从未登录的用户!

在 SQL/sqlalchemy 中,我会这样做:

1) 使用左连接选择根本没有登录的行

never_loggedin = session.query(User).join(Login,
Logins.user_id == User.id).\
        filter(Login.user_id == None)

2) 选择使用 Firefox 的登录名并只选择计数小于 5 的登录名。

sub_query = session.query(Login).filter(Login.browser ==
browser).subquery() 
less_ex = session.query(User).outerjoin(sub_query,
sub_query.c.user_id ==
User.id).group_by(sub_query.c.user_id).having(func.count(User.id) <
repetition) 

3) 现在我有问题了。可能有用户登录但从不使用 Firefox,并且这些用户不是从以前的查询中选择的。我不知道如何选择那些。

我的操作正确吗?具体来说,我想我应该使用多对多关系,但我想我会把这个编辑放在软件的下一次重构中。

【问题讨论】:

  • 哼..也许只是一个选择,而“不在”选择可能是解决方案......

标签: mysql orm sqlalchemy


【解决方案1】:
  sub_query = session.query(Login.user_id).filter(Login.browser == browser).group_by(Login.user_id).having(func.count(Login.id) >= repetition).subquery()
  less = session.query(User).filter(~User.id.in_(sub_query))

【讨论】:

    猜你喜欢
    • 2014-03-09
    • 2021-05-07
    • 2012-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-05
    • 2018-02-22
    相关资源
    最近更新 更多