【问题标题】:order by before group by in sqlalchemy在sqlalchemy中的group by之前排序
【发布时间】:2022-01-10 10:19:45
【问题描述】:

想在我的表中获得最后 2 个 name 例如

id    name    price
1     name1   100
2     name2   120
3     name3   100
4     name3   150
5     name3   152

我希望结果变成

name
name3
name2

已经搜索过类似的问题here,但在 SQLalchemy 中找不到答案

我的尝试

orders = db.session.query(Table.name).filter(SomeFilter).order_by(Table.id.desc()).group_by(
        Table.name).all() 

问题是group_byorder_by 同时使用limit 没有问题

EDIT2

result = session.query(test).order_by(test.i.desc()).with_entities(test.j).distinct(test.j).limit(2)

postgress 也会出错

【问题讨论】:

  • 使用limit(),见:Sqlalchemy get last X rows in order
  • 想要group_bylimit 如果使用group_by limit 不能正常工作
  • 问题是order by 之后group by 将按脂肪族顺序排序我想按更新时间排序

标签: python-3.x postgresql sqlalchemy


【解决方案1】:

好的,我(非常)是 sqlalchemy 的新手(所以不要在此代码的开头提及“大量”导入 ?),但请参阅我的代码:


import sqlalchemy

from sqlalchemy import create_engine, Column, String, Integer, MetaData, Table
from sqlalchemy import text
from sqlalchemy.orm import Session
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine("sqlite+pysqlite:///test.db", echo=True)

Base = declarative_base()
metadata = MetaData(engine)
class test(Base):
    __tablename__ = 'test'
    i = Column(Integer,primary_key=True)
    j = Column(Integer)

with Session(engine) as session:
    session.execute("""CREATE TABLE test(i int primary key,j int)""")
    session.execute("""DELETE FROM test""")
    t1 = test(i=1, j=1)
    session.add(t1)
    session.add(test(i=2,j=5))
    session.add(test(i=3,j=5))
    session.add(test(i=4,j=2))
    session.add(test(i=5,j=2))
    session.add(test(i=6,j=3))
    session.add(test(i=7,j=3))
    session.add(test(i=8,j=3))

    session.commit()
    result = session.query(test).group_by(test.j).order_by(test.j.desc()).limit(2)
    for row in result:
          print(f"I: {row.i}  J: {row.j}")

顺便说一句:DELETE FROM... 仅在第二次运行时才需要,当我用 CREATE TABLE.... 注释该行时

输出是:

I: 6  J: 3
I: 4  J: 2

编辑:项目应按i desc 排序。为此,您可以使用以下代码:

(注意:j=1 改为 j=5,才能得到正确的结果)

    subquery = session.query(test).order_by(test.i.desc()).with_entities(test.j).subquery()
    result = session.query(subquery).distinct().limit(2)
    for row in result:
          print(f"J: {row.j}")

使用我的示例数据返回:

J: 3
J: 2

EDIT2:在这里发布代码后总会出现更好的结果......?

不用子查询也可以做到:

result = session.query(test).order_by(test.i.desc()).with_entities(test.j).distinct(test.j).limit(2)

EDIT3:似乎 postgresql 出现错误(请参阅 cmets)。

需要进行以下更改才能解决此问题(在 PG::Error: SELECT DISTINCT, ORDER BY expressions must appear in select list 的帮助下:

  • 添加from sqlalchemy import func
  • create engine(sqlite... 更改为create_engine("postgresql://user:password@localhost/dbname", echo=True,)
  • 最终选择如下:
    result = session.query(test).order_by(func.min(test.i).desc()).with_entities(test.j).group_by(test.j).limit(2)
    for row in result:
          print(f"J: {row.j}")

另请参阅 (Postgres14):DBFIDDLE

另见(SQLite):DBFIDDLE

或 DBFIDDLE 的并排:https://dbfiddle.uk/?rdbms=sqlite_3.27&rdbms2=postgres_14&fiddle=afd9687da44ec2ce2c66d9e08ee38b18

【讨论】:

  • 这将按名称的脂肪顺序排序,我想在 group by 之前排序或根据 id desc 排序,换句话说,按 id 排序,然后按 name 分组
  • 对不起,我的英语听不懂你想说什么(我不是以英语为母语的人)
  • 将代码中的j=1更改为j=5并检查结果,结果必须相同但代码将返回5和3
  • 好的,所以你似乎想要这个DBFIDDLE中最后一条SQL语句的结果
  • 添加了一个 EDIT 和一个 EDIT2。
猜你喜欢
  • 2011-11-18
  • 2015-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多