3

我有以下表定义:

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 中做到这一点(它们可能比我的描述更清楚地说明我想要什么):

filter(lambda u: u not in self.subscribes, self.subscribed)
# OR: set(self.subscribed) - set(self.subscribes)

但是如果在 SQL 端完成会不会更快?

4

3 回答 3

3

如果这是在 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
于 2012-08-08T20:02:57.227 回答
2

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

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())
于 2012-08-08T22:14:21.330 回答
0

如果您的数据库是 Oracle,您可以使用“MINUS”关键字,该关键字适用于集合,就像您最终评论中的减号一样。以下是一个结构类似于“UNION”查询的单个语句:

SELECT subscriber_id FROM subscriptions WHERE subscribee_id = :myuid
MINUS
SELECT subscribee_id FROM subscriptions WHERE subscriber_id = :myuid

或者,如果“MINUS”不可用,您可以使用“NOT IN”;

SELECT subscriber_id
FROM subscriptions
WHERE subscribee_id = :myuid
  AND subscriber_id NOT IN
        (SELECT subscribee_id FROM subscriptions WHERE subscriber_id = :myuid)
于 2012-08-08T20:20:16.640 回答