Python sqlalchemy-连接表的限制,就像它们未连接的地方一样

Python sqlalchemy-连接表的限制,就像它们未连接的地方一样,python,sql,postgresql,sqlalchemy,Python,Sql,Postgresql,Sqlalchemy,我使用的是sqlalchemy,我想从用户那里获取以下数据,并按照给定给表的顺序应用这些操作: 用于筛选数据的关键字、要排序的列、限制和页面 数 现在我有很多桌子。大多数“children”表(一个没有子表的表)都可以工作。然而,我有一张桌子,上面有各种各样的关系。。双方一对多,一对一,多对多 为了实现上述操作,我事先加入了所有表。过滤和排序工作正常,但limit并没有给我想要的结果 Join语句: records = m.Activity.query.join(m.Event, m.Activ

我使用的是sqlalchemy,我想从用户那里获取以下数据,并按照给定给表的顺序应用这些操作:

用于筛选数据的关键字、要排序的列、限制和页面 数

现在我有很多桌子。大多数“children”表(一个没有子表的表)都可以工作。然而,我有一张桌子,上面有各种各样的关系。。双方一对多,一对一,多对多

为了实现上述操作,我事先加入了所有表。过滤和排序工作正常,但limit并没有给我想要的结果

Join语句:

records = m.Activity.query.join(m.Event, m.Activity.events) \
            .join(m.DateLocation, m.Activity.date_locations) \
            .join(m.Goal, m.Activity.goals) \
            .join(m.Type, m.Activity.type)
过滤和排序包含大量不必要的信息,基本上如下所示:

# filtering if column == event
records = records.filter(m.Event.name == keyword) 
# ordering if column == type and desc was chosen
records = records.order_by(m.Type.name.desc())
最后是限制和分页:

records = records.limit(limit)
records = records.offset((page - 1) * limit)
让我解释一下极限行为与我想要的:

此代码中的限制可以正常工作。由于我加入了所有的表,它将返回我给它的加入行数。。例如,如果连接导致额外的5行,并且我要求限制5行,那么无论原始表id如何,它都将返回前5行

我想要的是加入前的限制行为。我加入他们只是为了过滤或按他们排序。之后,当我说limit(5)时,我想返回前5个带有不同ID的结果

我尝试了以下方法(一次一个),但没有成功:

records = records.distinct(m.Activity.id).limit(limit)
records = records.group_by(m.Activity.id).limit(limit)
records = records.from_self().limit(limit)
我尝试了提出的解决方案。它确实可以工作,但是它在加入之前限制了数据集。这在我的情况下不起作用,因为我需要限制过滤的数据

编辑:模型:

EventsInActivities = db.Table(
    'events_in_activities',
    db.Column('activity_id', db.String, db.ForeignKey('activity.id')),
    db.Column('event_id', db.Integer(), db.ForeignKey('event.id'))
)


class Event(db.Model, BaseMixin):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String)


class Type(db.Model, BaseMixin):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String, unique=True)
    activities = db.relationship("Activity", backref="type", lazy='dynamic')


class Goal(db.Model, BaseMixin):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    activity_id = db.Column(db.String, db.ForeignKey('activity.id'), primary_key=True)
    name = db.Column(db.String())


class DateLocation(db.Model, BaseMixin):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    activity_id = db.Column(db.String, db.ForeignKey('activity.id'), primary_key=True)
    start_date = db.Column(db.DateTime)
    end_date = db.Column(db.DateTime)
    location = db.Column(db.String())


class Activity(db.Model, BaseMixin):
    id = db.Column(db.String, primary_key=True)
    name = db.Column(db.String())
    type_id = db.Column(db.Integer, db.ForeignKey('type.id'))
    date_locations = db.relationship("DateLocation", order_by='DateLocation.start_date', cascade="all, delete", backref="activity", lazy='dynamic')
    goals = db.relationship("Goal", cascade="all, delete", backref="activity", lazy='dynamic')
    events = db.relationship('Event', secondary=EventsInActivities, backref=db.backref('activities', lazy='dynamic'))

您可以使用子查询表达式或以某种方式替换筛选器的至少一些联接。这样,查询就避免了为单个活动生成多行。仍然可以根据
类型加入,因为这是一种多对一关系:

records = m.Activity.query.\
    join(m.Activity.type).\
    filter(m.Activity.events.any(name=keyword)).\
    filter(m.Activity.goals.any(name=...)).\
    filter(...).\
    order_by(m.Type.name.desc()).\
    limit(limit).\
    offset((page - 1) * limit)
将关键字参数传递给类似于。它还接受复杂的标准表达式和位置参数

distinct(m.Activity.id)
或distinct ON也应该有效,只要您将结果用作子查询,然后对其应用排序和限制:

records = m.Activity.query.\
    join(m.Activity.events).\
    join(m.Activity.date_locations).\
    join(m.Activity.goals).\
    filter(m.Event.name == keyword).\
    filter(...).\
    distinct(m.Activity.id).\
    from_self().\
    join(m.Activity.type).\
    order_by(m.Type.name.desc()).\
    limit(limit).\
    offset((page - 1) * limit)

@IljaEverilä刚刚添加了模型,它成功了!非常感谢。对于任何感兴趣的人来说,我使用的第一个解决方案是,它与我的代码的其余部分配合得更好,只是一个简单的问题。。例如,你会如何通过目标来排序?这取决于。每个活动的所有相关目标是否具有相同的名称?如果没有,你会选择哪一项?每项活动都有不同的目标。。大多数人拥有一个目标,但一项活动可能有多个目标。事件也是如此。真正的问题是日期位置,因为每个活动都有两个具有不同值的位置。我想做一些事情,比如在开始日期之前订购它们。然后使用不同的活动id,并将其显示为“按开始日期订购”和“开始日期”您的意思是至少要按
日期地点订购。每个
活动的开始日期
?这是个问题。总而言之,你如何从各自的分组中选择一个
目标
事件
,或者我误解了,这有点不清楚。你的意思是你想急切地加载目标等,排序?