【问题标题】:SQLAlchemy: exclude rows taken from a subquery on a querySQLAlchemy:排除从查询的子查询中获取的行
【发布时间】:2015-08-25 18:57:20
【问题描述】:

抽象我的问题,我有 2 个tables。一个 User 表和一个 Friendship 表。

我正在尝试使用 SQLAlchemy 进行查询以列出所有可添加为用户 1 Alice 的朋友的用户,并且不包括她自己。

考虑到可能有很多朋友,找爱丽丝的朋友:

friend_subquery = db.session.query(Friendship).filter_by(User_id=1).subquery()

现在我想要列出所有用户,除了 Alice 和她的朋友 Bob 和 Jack。

friends = (db.session.query(User).
            filter(User.ID != 1).
            outerjoin(friend_subquery,
                      User.ID != friend_subquery.c.Friend_id))

我的预期结果是获得用户 4 和 5,但是这个查询 返回除了爱丽丝本人之外的所有人。

的条件
User.ID != friend_subquery.c.Friend_id

似乎没有按预期工作。

附:我已经完成了搜索、阅读文档的作业,但无法弄清楚。感谢您的宝贵时间。

【问题讨论】:

    标签: python orm sqlalchemy


    【解决方案1】:

    我假设您的模型定义如下:

    class User(db.Model):
        __tablename__ = 'User'
    
        ID = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(100))
    
        friendships = db.relationship(
            'Friendship',
            foreign_keys='Friendship.User_id',
            backref='friender',
        )
        friendships_of = db.relationship(
            'Friendship',
            foreign_keys='Friendship.Friend_id',
            backref='friendee',
        )
    
    
    class Friendship(db.Model):
        __tablename__ = 'Friendship'
        ID = db.Column(db.Integer, primary_key=True)
        User_id = db.Column(db.Integer, db.ForeignKey('User.ID'))
        Friend_id = db.Column(db.Integer, db.ForeignKey('User.ID'))
    

    在这种情况下,执行此查询的两种方法显示在下面的代码中。第一个查询依赖于relationshipUser.friendships_of,而第二个查询使用显式连接:

        # Add users
        u1, u2, u3, u4, u5 = users = [
            User(name="Alice"),
            User(name="Bob"),
            User(name="Jack"),
            User(name="Pluto"),
            User(name="Mike"),
        ]
        db.session.add_all(users)
    
        # Add friendhips
        u1.friendships.append(Friendship(friendee=u2))
        u1.friendships.append(Friendship(friendee=u3))
        db.session.commit()
    
        # Find Alice
        u_alice = db.session.query(User).filter(User.name == 'Alice').one()
    
        # Query (version 1)
        q = (
            db.session.query(User)
            .filter(~User.friendships_of.any(Friendship.User_id == u_alice.ID))
            .filter(User.ID != u_alice.ID)
            .all()
        )
        for x in q:
            print(x)
    
        # Query (version 2)
        q = (
            db.session.query(User)
            .outerjoin(
                Friendship,
                db.and_(
                    u_alice.ID == Friendship.User_id,
                    User.ID == Friendship.Friend_id,
                )
            )
            .filter(Friendship.ID == None)
            .filter(User.ID != u_alice.ID)
            .all()
        )
        for x in q:
            print(x)
    

    【讨论】:

    • 我通过显式连接尝试了第二个查询,它确实有效。获得 15 名声望后,我会立即投票赞成您的回答。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2018-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-05
    • 2020-10-27
    • 1970-01-01
    相关资源
    最近更新 更多