Using PostgreSQL Aggregate ORDER BY with sqlalchemy

前端 未结 3 531
囚心锁ツ
囚心锁ツ 2021-01-18 23:46

I have a query which uses PostgreSQL\'s syntax for using ORDER BY in an aggregate function, something like this:

SELECT some_agg_func(a ORDER BY b DESC) FROM         


        
相关标签:
3条回答
  • 2021-01-19 00:24

    From the SQLAlchemy Docs:

    from sqlalchemy.dialects.postgresql import aggregate_order_by
    
    expr = func.array_agg(aggregate_order_by(table.c.a, table.c.b.desc()))
    stmt = select([expr])
    
    0 讨论(0)
  • 2021-01-19 00:31

    I think SqlAlchemy 1.1 has native support for string_agg now: http://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#sqlalchemy.dialects.postgresql.aggregate_order_by (search the page for "func.string_agg")

    0 讨论(0)
  • 2021-01-19 00:38

    You need to use SQLAlchemy's compiler extension to achieve this. Here's an example for Postgres string_agg function:

    from sqlalchemy.sql.expression import ColumnElement, _literal_as_column
    from sqlalchemy.dialects import postgresql
    from sqlalchemy.ext.compiler import compiles
    
    class string_agg(ColumnElement):
        def __init__(self, expr, separator, order_by=None):
            self.type = Text()
            self.expr = _literal_as_column(expr)
            self.separator = literal(separator)
            self.order_by = _literal_as_column(order_by)
    
        @property
        def _from_objects(self):
            return self.expr._from_objects
    
    @compiles(string_agg, 'postgresql')
    def compile_string_agg(element, compiler, **kwargs):
        head = 'string_agg(%s, %s' % (
            compiler.process(element.expr),
            compiler.process(element.separator)
        )
        if element.order_by is not None:
            tail = ' ORDER BY %s)' % compiler.process(element.order_by)
        else:
            tail = ')'
        return head + tail
    
    query = session.query(string_agg(Foo.bar, ', ', order_by=Foo.bar.desc()))
    # Print compiled SQL query.
    print query.statement.compile(dialect=postgresql.dialect())
    # Run the query and print result.
    print query.scalar()
    
    0 讨论(0)
提交回复
热议问题