Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python SQLAlchemy多对多查询通过和限制其他表进行排序_Python_Sql_Sqlalchemy_Flask Sqlalchemy - Fatal编程技术网

Python SQLAlchemy多对多查询通过和限制其他表进行排序

Python SQLAlchemy多对多查询通过和限制其他表进行排序,python,sql,sqlalchemy,flask-sqlalchemy,Python,Sql,Sqlalchemy,Flask Sqlalchemy,我正在尝试加入3个表,电影,角色,演员。我的代码执行时没有错误,但当我试图打印数据时,我只能访问第一个表上的信息 role = db.Table('role', db.Column('movie_id', db.Integer, db.ForeignKey('movie.id')), db.Column('actor_id', db.Integer, db.ForeignKey('actor.id'))) class Mov

我正在尝试加入3个表,电影,角色,演员。我的代码执行时没有错误,但当我试图打印数据时,我只能访问第一个表上的信息

role = db.Table('role',
                 db.Column('movie_id', db.Integer, db.ForeignKey('movie.id')),
                 db.Column('actor_id', db.Integer, db.ForeignKey('actor.id')))


class Movie(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(20), nullable=False)
    genre = db.Column(db.Text)
    year = db.Column(db.Integer)
    characters = db.relationship('Actor',lazy='dynamic',
                         secondary=role,
                         backref=db.backref('movies', lazy='dynamic')) #  updated


class Actor(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.String(200), nullable=False)
    picture = db.Column(db.String(200), nullable=False)
    age = db.Column(db.Integer)


query = Movie.query.join(role).join(Actor).filter_by(Movie.year==1974)
显示查询后,我将无法访问有关参与者的信息

编辑:我希望能够筛选、限制和排序联接的参与者表。示例:query=Movie.query.joinrole.joinActor.order_byActor.age.desc.limit4.filter_byMovie.year==1974

更新:我试图将snakecharmerb提供的原始sql查询转换为sqlalchemy,但遇到了障碍。这就是我到目前为止所做的:

    query = select(select(Movie.title, Actor.first_name, Actor.age, func.row_number().over(partition_by=role.c.movie_id, order_by=Actor.age.desc())).label("rn")
                   {???????}.label("m")
                   .join(role, (role.c.movie_id == movie.id))
                   .join(Actor, (role.c.actor_id == actor.id)))
                   .where("rn <= 4")
但我希望还有最后一个问题。返回的数据是一个平面列表

[
    ('movie name 1', "actor name 1", 1),
    ('movie name 1', 'actor name 2', 2),
    ('movie name 1', 'actor name 3', 3),
    ('movie name 1', 'actor name 4', 4),
    ('movie name 2', 'actor name 1', 1),
    ('movie name 2', 'actor name 7', 2),
    ('movie name 2', 'actor name 4', 3),
    ('movie name 2', 'actor name 2', 4),
    ('movie name 3', 'actor name 8', 1),
    ('movie name 3', 'actor name 9', 2)
我希望我能得到这样的东西

    ('movie name 1', ["actor name 1",
                      'actor name 2',
                      'actor name 3',
                      'actor name 4']),
    ('movie name 2', ['actor name 1',
                      'actor name 7',
                      'actor name 4',
                      'actor name 2']),
    ('movie name 3', ['actor name 8',
                      'actor name 9']),
]
我想我可以使用.group_by来实现这一点,但我一直无法让它正常工作。

需要重新定义电影和演员之间的关系,以便在电影端动态加载。我还重命名了backref,以便您可以使用演员。电影:

characters=db.relationship'Actor', “动态”, 次要=角色, backref=db.backref'movies',lazy='dynamic' 完成后,可以为每部电影查询Movie.characters 此示例是纯sqlalchemy,但转换为flask sqlalchemy并不困难:

从sqlalchemy导入orm query=session.queryMovie.filterMovie.year==1974 对于查询中的电影: 电影名称 对于电影中的演员.characters.order_byActor.age.desc.limit4: printactor.first_name,actor.age 打印 就效率而言,限制每部电影返回的演员数量是好的,但是使用动态加载意味着我们生成一个查询来获取电影,然后生成一个查询来获取每部电影的角色,这就是问题所在。这也不是很有效

使用纯SQL,可以通过此查询检索所需的数据:

sub_query = db.session.query(Movie.title, Actor.first_name, Actor.age,
func.row_number().over(partition_by=role.c.movie_id).label('rn'))\
    .join(role, (role.c.movie_id == movie.id))
    .join(Actor, (role.c.actor_id == actor.id)).subquery()
query = db.session.query(sub_query).filter(text('rn <= 4'))
从中选择*选择m.title、a.first\u name、a.age、按r.movie\u id分区的行数按a.age DESC AS rn排序 从电影m 在r.movie\u id=m.id上加入角色r 在r.actor\u id=a.id上加入actors a 其中m.year=1974 dummy,其中rn需要重新定义电影和演员之间的关系,以便在电影端动态加载。我还重命名了backref,以便可以使用演员。电影:

characters=db.relationship'Actor', “动态”, 次要=角色, backref=db.backref'movies',lazy='dynamic' 完成后,可以为每部电影查询Movie.characters 此示例是纯sqlalchemy,但转换为flask sqlalchemy并不困难:

从sqlalchemy导入orm query=session.queryMovie.filterMovie.year==1974 对于查询中的电影: 电影名称 对于电影中的演员.characters.order_byActor.age.desc.limit4: printactor.first_name,actor.age 打印 就效率而言,限制每部电影返回的演员数量是好的,但是使用动态加载意味着我们生成一个查询来获取电影,然后生成一个查询来获取每部电影的角色,这就是问题所在。这也不是很有效

使用纯SQL,可以通过此查询检索所需的数据:

sub_query = db.session.query(Movie.title, Actor.first_name, Actor.age,
func.row_number().over(partition_by=role.c.movie_id).label('rn'))\
    .join(role, (role.c.movie_id == movie.id))
    .join(Actor, (role.c.actor_id == actor.id)).subquery()
query = db.session.query(sub_query).filter(text('rn <= 4'))
从中选择*选择m.title、a.first\u name、a.age、按r.movie\u id分区的行数按a.age DESC AS rn排序 从电影m 在r.movie\u id=m.id上加入角色r 在r.actor\u id=a.id上加入actors a 其中m.year=1974
dummy其中rn可以限制使用此方法返回的参与者的数量吗?我似乎只能限制电影的数量。我用一些有用的东西编辑了我的答案。我还没有将该SQL查询转换为sqlalchemy,但可能稍后再试。是否可以限制使用此方法返回的参与者数量?我似乎只能限制电影的数量。我用一些有用的东西编辑了我的答案。我还没有成功地将该SQL查询转换为sqlalchemy,但可能稍后再试。除了LIMIT子句之外,几乎可以实现这一点。@snakecharmerb是否不可能在查询中执行筛选、限制和排序,而不是像我在示例中尝试的那样执行模型?就性能而言,当理论上可以得出1000个结果时,是否值得继续尝试将联接表限制为4个结果?@snakecharmerb我使用的是postgres。除了LIMIT子句之外,几乎可以实现这一点。@snakecharmerb是否不可能在查询中执行筛选、限制和排序,而不是像我在示例中尝试的那样执行模型?就性能而言,当理论上可以得出1000个结果时,是否值得继续尝试将联接表限制为4个结果?@snakecharmerb我使用的是postgres。