Python SQLite与PostgreSQL的SQLAlchemy group_

Python SQLite与PostgreSQL的SQLAlchemy group_,python,postgresql,sqlite,group-by,sqlalchemy,Python,Postgresql,Sqlite,Group By,Sqlalchemy,对于我们正在构建的web应用程序,我们使用SQLite进行测试。最近我们想迁移到PostgreSQL。问题就是从这里开始的: 我们有这个SQLAlchemy模型(简化) 我想将所有实体按某个值进行分组,我喜欢这样做(简化): 在SQLite中,这是有效的。回想起来,我发现它没有意义,但SQLite确实有意义。我不能确定返回了哪些实体 现在在PostgrSQL中,我们得到了以下错误: sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingErr

对于我们正在构建的web应用程序,我们使用SQLite进行测试。最近我们想迁移到PostgreSQL。问题就是从这里开始的:

我们有这个SQLAlchemy模型(简化)

我想将所有
实体
某个值
进行分组,我喜欢这样做(简化):

在SQLite中,这是有效的。回想起来,我发现它没有意义,但SQLite确实有意义。我不能确定返回了哪些实体

现在在PostgrSQL中,我们得到了以下错误:

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) column "entity.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT entity.id AS entity_id, entity.i_want_this AS entity_not...
^
[SQL: 'SELECT entity.id AS entity_id, entity.i_want_this AS entity_i_want_this, count(*) AS count_1 \nFROM entity GROUP BY entity.some_value']
这个错误完全有道理

所以我的第一个问题是:SQLite为什么允许这样做?它是如何做到的(使用了什么隐藏聚合)?

我的第二个问题很明显:如何使用PostgreSQL?

实际上我只对计数和第一个
感兴趣,我想要这个
值。所以我可以这样做:

groups = db.session.query(db.func.min(Entity.id), db.func.count()).group_by(Entity.some_value)

[(Entity.query.get(id_), count) for id_, count in groups]
但我不希望这些额外的
get
查询

因此,我想选择第一个实体(id最小的实体)和按
some\u value
分组的实体数,或者选择第一个
I\u want\u this
和按
some\u value
分组的计数

编辑以澄清:

  • 我想按
    某些值进行分组
    (完成)
  • 我想获得每个组中的实体数(完成)
  • 我想获得每个组中id最低的实体(需要帮助)
  • 或者,我想获得每组中id最低的实体的
    I\u want\u this
    值(需要帮助)

关于您的第一个问题,请检查:

然后,对结果集中的每个表达式分别计算一次 一组行。如果表达式是聚合表达式,则为 跨组中的所有行计算。否则,将对其进行评估 针对组内任意选择的一行。如果 结果集中有多个非聚合表达式, 然后对同一行计算所有此类表达式

关于第二个问题,考虑到您当前在SQLite中的查询也会或多或少地返回随机结果,您可能必须解释您实际想要实现的目标

编辑: 要获取每个组具有最小id的实体,可以使用
查询。从
构造中选择\u:

import sqlalchemy.sql as sa_sql

# create the aggregate/grouped query
grouped = sa_sql.select([sa_sql.func.min(Entity.id).label('min_id')])\
                .group_by(Entity.some_value)\
                .alias('grouped')

# join it with the full entities table
joined = sa_sql.join(Entity, grouped, grouped.c.min_id == Entity.id)
# and let sqlalchemy pull the entities from this statement:
session.query(Entity).select_from(joined)
这将生成以下SQL:

SELECT entities.id AS entities_id,
       entities.i_want_this AS entities_i_want_this,
       entities.some_value AS entities_some_value 
FROM entities JOIN (SELECT min(entities.id) AS min_id
                    FROM entities GROUP BY entities.some_value) AS grouped
ON grouped.min_id = entities.id

关于第一个问题,请检查:

然后,对结果集中的每个表达式分别计算一次 一组行。如果表达式是聚合表达式,则为 跨组中的所有行计算。否则,将对其进行评估 针对组内任意选择的一行。如果 结果集中有多个非聚合表达式, 然后对同一行计算所有此类表达式

关于第二个问题,考虑到您当前在SQLite中的查询也会或多或少地返回随机结果,您可能必须解释您实际想要实现的目标

编辑: 要获取每个组具有最小id的实体,可以使用
查询。从
构造中选择\u:

import sqlalchemy.sql as sa_sql

# create the aggregate/grouped query
grouped = sa_sql.select([sa_sql.func.min(Entity.id).label('min_id')])\
                .group_by(Entity.some_value)\
                .alias('grouped')

# join it with the full entities table
joined = sa_sql.join(Entity, grouped, grouped.c.min_id == Entity.id)
# and let sqlalchemy pull the entities from this statement:
session.query(Entity).select_from(joined)
这将生成以下SQL:

SELECT entities.id AS entities_id,
       entities.i_want_this AS entities_i_want_this,
       entities.some_value AS entities_some_value 
FROM entities JOIN (SELECT min(entities.id) AS min_id
                    FROM entities GROUP BY entities.some_value) AS grouped
ON grouped.min_id = entities.id

SQLite从组中的随机行返回一个值。但你说“第一”是什么意思?SQL表没有排序。我指的是在上一个代码片段中看到的id最低的实体。SQLite从组中的随机行返回一个值。但你说“第一”是什么意思?SQL表没有排序。我指的是上一段代码中id最低的实体。