this is a new (and extremely awkward, wow) kind of SQL compilation arrangement. Two ways to do it:
1. just use a string. connection/session.execute("select * from ..."). this syntax is totally specific to Postgresql in any case. It's unlikely you need lots of fluency here as the construct is so awkward to start with.
from sqlalchemy.sql import ColumnElement, FromClause, column, literal_column
from sqlalchemy.ext.compiler import compiles
"""
SELECT *
FROM crosstab(
'select rowid, attribute, value
from ct
where attribute = ''att2'' or attribute = ''att3''
order by 1,2')
AS ct(row_name text, category_1 text, category_2 text, category_3 text);
"""
class crosstab(FromClause):
def __init__(self, name, stmt, columns):
self.stmt = stmt
self.columns = columns
def _populate_column_collection(self):
self._columns.update(
column(name, type=type_)
for name, type_ in self.names
)
def crosstab_param(value):
# we can't use bound parameters in crosstab?
return literal_column("''%s''" % value)
@compiles(crosstab)
def visit_element(element, compiler, **kw):
return """
crosstab('%s order by 1, 2') AS %s(%s)
""" % (
compiler.visit_select(element.stmt),
", ".join(
"%s %s" % (
c.name, compiler.visit_typeclause(c))
for c in element.c
)
)
from sqlalchemy import Table, Column, MetaData, Text, or_, select
m = MetaData()
ct = Table('ct', m, Column('rowid', Text),
Column('attribute', Text),
Column('value', Text))
stmt = select([ct]).where(
or_(
ct.c.attribute == crosstab_param('att2'),
ct.c.attribute == crosstab_param('att3')
)
)
print select(['*']).select_from(crosstab("ct", stmt, ct.c))