SQLAlchemy从查询中获取ID列表

16

如何获得一个ID列表而不是SQLAlchemy对象列表?当前我正在这样做:

[x.id for x in random_query.all()]

有没有更好的方法来做这件事,最好只使用SQLAlchemy语句。

6个回答

15

SQL

 SELECT DISTINCT `id` FROM `table`;

Python

 for value in Session.query(Table.id).distinct():
     #Do something Append

3
[x.id for x in random_query.all()][x.id for x in random_query.distinct()] 之间究竟有什么区别? - JelteF
2
你要找的是 query(Table.id).distinct().distinct() 通过使用我上面的 SQL 语句返回仅具有唯一性的结果。如果你的 id 列被定义为主键,则它本身就是唯一的。但是,如果不是,则 .all() 可能会多次返回多个 id。 - 1478963
4
好的,没问题。唯一的问题是它返回一个仅包含ID的元组列表。 - JelteF
@JelteF 可以使用for value, in session.query(Table.id).distinct():来解决这个问题。 - wizzwizz4

7
使用with_entities()时,为了尽可能准确地得到原始问题的答案,您将获得ID列表而不是SQLAlchemy对象列表。
User.query.with_entities(User.id).all()

把它想象成,不是执行完整的select查询...
SELECT * FROM user

您只需选择您感兴趣的字段:

SELECT id FROM user

说实话,您获得的是一个由1个元素组成的元组列表:
[(7,), (11,), (15,), (21,), (37,)]

所以最终答案是:

ids = [id[0] for id in User.query.with_entities(User.id).all()]

请注意,您只需要使用 with_entities,因为您正在使用 flask-sqlalchemy,它会自动将模型类映射到查询中。 - snakecharmerb
@snakecharmerb 好观点!我不知道这仅适用于Flask-SQLAlchemy。 - sscalvo

7

SQLAlchemy Session 有一个名为 scalars 的方法,用于获取不需要映射的值列表。

SQLAlchemy 1.4+ style:
results = Session.scalars(select(Table.id)).all()

SQLAlchemy 旧风格:

results = Session.scalars(Session.query(Table.id)).all()
results = Session.scalars(Table.query.with_entities(Table.id)).all()

实际 结果

[1, 2, 3, 4, 5]

3
session.query(Thing.id).all()

通常情况下,您查询整个对象,但也可以查询属性。

2

0
FYI,我得到的列表是以元组的形式返回的,所以我觉得做这样的操作很有用。我使用了直接从SQLACODEGEN中获取的类,不幸的是它使用了一种返回浮点数的通用Numeric,因此需要进行类型转换。
ids = list(map(lambda x: int(x[0]), \   
session.query(Trgmst.trgmst_id).filter(Trgmst.trgmst_trigger==trigger).all()))

我最初在我的情况下考虑做这样的事情...

ids = list(map(lambda x: int(x[0]), \
session.query(Trgmst.trgmst_id).filter(Trgmst.trgmst_trigger==trigger).all()))
return session.query(Trgjob).filter( \
    and_(Trgjob.jobmst_id==jobmst_id, Trgjob.trgmst_id.in_(ids)) \
    ).count() > 0

但最终我选择了这个:

return session.query(Trgjob).join(Trgjob.trgmst). \
    filter(Trgjob.jobmst_id==jobmst_id). \
    filter(Trgmst.trgmst_trigger==trigger). \
    count() > 0

这是因为我正在过滤连接文件的属性。

trgmst 是从 TrgjobTrgmst 的关系。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接