好的,我(非常)是 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