SQLAlchemy - 以与IN子句

时间:2016-02-10 13:41:21

标签: python sql postgresql sqlalchemy

我有一个球队名单。对于列表中的每个团队名称,我想从数据库中获取行,但我只想对数据库进行一次调用,并且sql炼金术对象列表需要保留原始列表的顺序。我将在原始列表中包含重复的名称。

我需要这样的东西,但是工作(我正在做的查询显然不起作用,因为它返回由id排序的所有内容)

teams_names = ['Liverpool', 'Arsenal', 'Utd', 'Liverpool']
Session.query(Team).filter(Team.name.in_(teams_names)).all()
teams_sa_obj = [#sa_liverpool, #sa_arsenal, #sa_utd, #sa_liverpool]

2 个答案:

答案 0 :(得分:3)

我通常在Python中进行重新排序。我的想法是你为Team个对象构建一个名称映射,然后在迭代原始列表时查找它们:

q = Session.query(Team).filter(Team.name.in_(teams_names))
team_map = {t.name: t for t in q}
teams = [team_map[n] for n in teams_names]

有SQL端解决方案,但这些与SQLAlchemy有点尴尬。

答案 1 :(得分:0)

PostgreSQL中一种尴尬的SQL解决方案是use WITH ORDINALITY and a JOIN

teams_names = ['Liverpool', 'Arsenal', 'Utd', 'Liverpool']

teams_names = text("""SELECT * 
                      FROM unnest(:teams_names) WITH ORDINALITY dummy(name, ord)""").\
    bindparams(teams_names=teams_names).\
    columns(name=String, ord=Integer).\
    alias()

Session.query(Team).\
    join(teams_names, teams_names.c.name == Team.name).\
    order_by(teams_names.c.ord).\
    all()

不幸的是,SQLAlchemy尚不支持WITH ORDINALITY,因此为了避免必须生成custom compiler extension,需要笨拙的text()构造,但是另一方面,自定义构造会提高的可读性。 Python代码。