我有以下表格定义:
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端完成它会不会更快?
答案 0 :(得分: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
答案 1 :(得分: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())
答案 2 :(得分: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)