【问题标题】:SQL-Alchemy join query - most efficient way to querySQL-Alchemy 连接查询——最有效的查询方式
【发布时间】:2014-08-02 00:07:27
【问题描述】:

我正在尝试生成一个查询,但很难在 sqlalchemy 中找到最有效的方法,(注意我使用的是 flask-sqlalchemy)

目标是找到所有用户都与特定用户会面。

假设 Frank 有 10 个会议即将召开,我想生成一个 frank 与之会面的所有人的列表。

这是我的模型:

class UserMeeting(db.Model):
    """ Associative table, links meetings to users in a many to many fashion"""
    __tablename__ = 'userMeeting'
    id = db.Column(db.Integer, primary_key = True)
    meeting_id = db.Column(db.Integer, db.ForeignKey('meeting.id'), primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)

class Meeting(db.Model):
    __tablename__ = "meeting"
    id = db.Column(db.Integer, primary_key = True)
    title = db.Column(db.String(128))
    #... other columns
    #associative reference
    attendees = db.relationship('UserMeeting', backref='meeting')

class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key = True)
    email = db.Column(db.String(128), index=True, unique=True)
    password = db.Column(db.String(128))
    #associative reference
    attendingMeetings = db.relationship("UserMeeting", backref="user", cascade="all, delete-orphan") 

这是我尝试过的:

#Assume frank's a user with id == 1
frank = User.query.get(1)
franks_meetings = Meeting.query.join(Meeting.attendees).filter(UserMeeting.user == frank).all()
#not efficient way of getting users in meetings with frank
users = []
for meeting in franks_meetings:
    for userMeeting in meeting.attendees:
        if userMeeting.user != frank:
            users.append(userMeeting.user)

#is there a way to just generate one query and get this data?

我似乎错过了如何使用连接来获取这些数据。任何帮助将不胜感激!

【问题讨论】:

  • 只是人员名单?不同的人?如果 Frank 不止一次与同一个人会面,那么您当前的代码就会受到欺骗,即使您没有跟踪每个人参加的会议。
  • 好点,我在我的例子中忽略了这一点。

标签: python sql flask sqlalchemy flask-sqlalchemy


【解决方案1】:

您需要将 UserMeeting 表与其自身连接,使用 meeting_id 作为连接键。您可能需要为该表设置别名才能引用它两次。我不知道我是否可以在脑海中为它输入 sqlalchemy 语法,但 sql 看起来像:

select distinct(b.user_id) as other_user_id
from usermeeting a
inner join usermeeting b
on a.meeting_id=b.meeting_id
where a.user_id=1 and b.user_id != 1;

1 是弗兰克。

哦,还有获取用户详细信息。可能你可以直接在 sqlalchemy 中直接得到 User 对象:

select distinct(u.id), u.email
from usermeeting a
inner join usermeeting b
on a.meeting_id=b.meeting_id
inner join users u
on b.user_id=u.id
where a.user_id=1 and b.user_id != 1;

【讨论】:

  • 感谢您的 SQL!加入 UserMeeting 本身正是我所需要的。
【解决方案2】:

这是查询的 sqlalchemy 版本供参考:

#get all users in meetings with Frank, (frank.id == 1)
um = aliased(UserMeeting)
frank = User.query.get(1)

q = session.query(User).join(User.attendingMeetings).\
    filter(UserMeeting.meeting_id == um.meeting_id).\
    filter(UserMeeting.user_id != frank.id, um.user_id == frank.id)

users_meeting_with_frank = q.all()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-26
    • 1970-01-01
    • 1970-01-01
    • 2016-05-10
    • 1970-01-01
    • 2016-03-20
    • 2014-12-01
    • 1970-01-01
    相关资源
    最近更新 更多