Python 选择订阅特定用户但该用户未订阅的所有用户

Python 选择订阅特定用户但该用户未订阅的所有用户,python,sql,sqlalchemy,many-to-many,flask-sqlalchemy,Python,Sql,Sqlalchemy,Many To Many,Flask Sqlalchemy,我有以下表格定义: subscriptions = db.Table("subscriptions", db.Column("subscriber_id", db.Integer, db.ForeignKey("users.id"), primary_key=True), db.Column("subscribee_id", db.Integer, db.ForeignKey("users.id"), primary_key=True), )

我有以下表格定义:

subscriptions = db.Table("subscriptions",
    db.Column("subscriber_id", db.Integer, db.ForeignKey("users.id"),
        primary_key=True),
    db.Column("subscribee_id", db.Integer, db.ForeignKey("users.id"), 
        primary_key=True),
)


class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)

    subscribes = db.relationship('User', secondary=subscriptions,
        backref=db.backref('subscribed'),
        primaryjoin="User.id==subscriptions.c.subscriber_id",
        secondaryjoin="User.id==subscriptions.c.subscribee_id",
    )
我需要形成一个查询,选择订阅某个特定用户但该用户未订阅的所有用户。我已经可以在Python中做到这一点(它们可能比我的描述更清楚地描述了我想要什么):


但是如果在SQL端执行,不是更快吗?

如果在SQL中执行,我相信您的查询将类似于以下内容:

SELECT
    u.id
FROM
    subscriptions sub  JOIN
    users u ON u.id = sub.subscriber_id LEFT JOIN
    subscriptions unsub
        ON unsub.subscribee_id = sub.subscriber_id
        AND unsub.subscriber_id= sub.subscribee_id 
WHERE
    sub.subscribee_id = :user_id
    AND unsub.subscribee_id IS NULL

如果您的数据库是Oracle,则可以使用“减号”关键字,该关键字将在集合上起作用,就像在最后的注释中使用减号一样。以下是一条结构类似于“UNION”查询的语句:

或者,如果“减”不可用,您可以使用“不在”


以下是SQLALchemy中的解决方案(它只是Michael Fredrickson解决方案的翻译):


这更像是一个SQL问题,而不是Python或SQLAlchemy问题。我编辑添加标签。我希望我有足够的代表投票支持你。将其转换为SQL炼金术可以满足我的需要。谢谢
SELECT
    u.id
FROM
    subscriptions sub  JOIN
    users u ON u.id = sub.subscriber_id LEFT JOIN
    subscriptions unsub
        ON unsub.subscribee_id = sub.subscriber_id
        AND unsub.subscriber_id= sub.subscribee_id 
WHERE
    sub.subscribee_id = :user_id
    AND unsub.subscribee_id IS NULL
SELECT subscriber_id FROM subscriptions WHERE subscribee_id = :myuid
MINUS
SELECT subscribee_id FROM subscriptions WHERE subscriber_id = :myuid
SELECT subscriber_id
FROM subscriptions
WHERE subscribee_id = :myuid
  AND subscriber_id NOT IN
        (SELECT subscribee_id FROM subscriptions WHERE subscriber_id = :myuid)
User1 = aliased(User)
sub = aliased(subscriptions)
unsub = aliased(subscriptions)


qry = db.session.query(User1).select_from(sub).\
    join(User1, User1.id==sub.c.subscriber_id).\
    filter(sub.c.subscribee_id==self.id).\
    outerjoin(unsub,
        and_(unsub.c.subscribee_id==sub.c.subscriber_id,
             unsub.c.subscriber_id==sub.c.subscribee_id)).\
    filter(unsub.c.subscribee_id==None).\
    order_by(User1.name.desc())