我正在使用SQLAlchemy处理postgres数据库。
我有一张这样的桌子
class Author(Base):
__tablename__ = "Author"
id = Column(BIGINT, primary_key=True)
name = Column(Unicode)
我想识别所有同名作者并将他们的id保存在一个列表中。
例如,如果数据库中有两个名为"John“的作者和3个名为"Jack”的作者,ID分别为11、22、33、44 a 55,我希望返回我的查询。
[("John", [11,22]), ("Jack", [33,44,55])]
现在我还能写
[x for x in db_session.query(
func.count(Author.name),
Author.name
).group_by(Author.name) if x[0]>1]
但这只会让我回想起
[(2,"John"),(3,"Jack")]
非常感谢您的帮助!
发布于 2022-06-02 02:25:49
在SQL中这样做的方法是使用PostgreSQL的array_agg
函数将ids分组为一个数组:
SELECT
name,
array_agg(id) AS ids
FROM
my_table
GROUP BY
name
HAVING
count(name) > 1;
array_agg
函数收集每个名称的ids,而HAVING
子句排除只有一行的ids。查询的输出如下所示:
name │ ids
═══════╪════════════════════
Alice │ {2,4,9,10,16}
Bob │ {1,6,11,12,13}
Carol │ {3,5,7,8,14,15,17}
转换为SQLAlchemy,查询将如下所示:
import sqlalchemy as sa
...
q = (
db_session.query(Author.name, sa.func.array_agg(Author.id).label('ids'))
.group_by(Author.name)
.having(sa.func.count(Author.name) > 1)
)
调用q.all()
将返回如下所示的(name, [ids])
元组列表:
[
('Alice', [2, 4, 9, 10, 16]),
('Bob', [1, 6, 11, 12, 13]),
('Carol', [3, 5, 7, 8, 14, 15, 17]),
]
在SQLAlchemy 1.4/2.0风格的语法中,等效于:
with Session() as s:
q = (
sa.select(Author.name, sa.func.array_agg(Author.id).label('ids'))
.group_by(Author.name)
.having(sa.func.count(Author.name) > 1)
)
res = s.execute(q)
https://stackoverflow.com/questions/72461664
复制相似问题