OK, I am (very) new to sqlalchemy (so do not mention the 'lot of' imports at the start of this code ), but see my code:
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}")
BTW: The DELETE FROM...
is only needed on second run, when I comment the line with CREATE TABLE....
the output is:
I: 6 J: 3
I: 4 J: 2
EDIT: The items should be sorted on i
desc. To get that done you can use the following code:
(NOTE: j=1 is changed to j=5, to get the correct result)
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}")
which, with my sample data, returns:
J: 3
J: 2
EDIT2: Better result always arise after posting the code here....
It can be done without subquery:
result = session.query(test).order_by(test.i.desc()).with_entities(test.j).distinct(test.j).limit(2)
EDIT3: It appears the postgresql is giving an error (see comments).
the following changes are needed to solve this (with help from PG::Error: SELECT DISTINCT, ORDER BY expressions must appear in select list:
- add
from sqlalchemy import func
- change
create engine(sqlite...
to create_engine("postgresql://user:password@localhost/dbname", echo=True,)
- finally the selection looks like:
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}")
see also (Postgres14): DBFIDDLE
see also (SQLite): DBFIDDLE
or the DBFIDDLE's side-by-side: https://dbfiddle.uk/?rdbms=sqlite_3.27&rdbms2=postgres_14&fiddle=afd9687da44ec2ce2c66d9e08ee38b18