简体   繁体   English

SQLAlchemy:排除从子查询中获取的行

[英]SQLAlchemy: exclude rows taken from a subquery on a query

Abstraction of my problem, I have 2 tables . 我的问题的抽象,我有2个 A User table, and a Friendship table. 用户表和友谊表。

I'm trying to make a query to list all the users available to be added as friend to User 1, Alice, and also excluding herself, using SQLAlchemy. 我正在尝试使用SQLAlchemy进行查询,以列出所有可作为好友添加到用户1,爱丽丝,还排除自己的用户。

Considering there could be a lot of friendships, to find Alice's friends: 考虑到可能有很多友谊,找到爱丽丝的朋友:

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

Now I want all the users listed, except Alice, and her friends, Bob and Jack. 现在,我希望列出所有用户,除了爱丽丝,她的朋友鲍勃和杰克。

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

My expected result would have been to get User 4 and 5, but this query returns all except Alice herself. 我的预期结果将是获得用户4和5,但是此查询将返回除爱丽丝本人以外的所有用户。 The condition of 条件

User.ID != friend_subquery.c.Friend_id

seem NOT to be working as expected. 似乎无法正常工作。

PS I've done my homework of searching, reading docs, but couldn't figure it out. 附注:我已经完成了搜索,阅读文档的作业,但无法弄清楚。 Thanks for your time. 谢谢你的时间。

I assumed that your models are defined as below: 我假设您的模型定义如下:

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'))

In which case two ways to perform this query is shown in the code below. 在这种情况下,以下代码显示了执行此查询的两种方法。 The first query relies on the relationship User.friendships_of , while the second works with explicit joins: 第一个查询依赖于User.friendships_of relationship ,第二个查询使用显式联接:

    # 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM