views:

139

answers:

1

I'm trying to convert this to something sqlalchemy expression language compatible, I don't know if it's possible out of box and are hoping someone more experienced can help me along. The backend is PostgreSQL and if I can't make it as an expression I'll create a string instead::

SELECT
    DISTINCT date_trunc('month', x.x) as date,
    COALESCE(b.res1, 0) AS res1,
    COALESCE(b.res2, 0) AS res2
FROM 
    generate_series(
        date_trunc('year', now() - interval '1 years'), 
        date_trunc('year', now() + interval '1 years'),
        interval '1 months'
    ) AS x
LEFT OUTER JOIN(
    SELECT
        date_trunc('month', access_datetime) AS when,
        count(NULLIF(resource_id != 1, TRUE)) AS res1,
        count(NULLIF(resource_id != 2, TRUE)) AS res2
    FROM tracking_entries
    GROUP BY 
        date_trunc('month', access_datetime)
    ) AS b
ON (date_trunc('month', x.x) = b.when)

First of all I got a class TrackingEntry mapped to tracking_entries, the select statement within the outer joined can be converted to something like (pseudocode)::

from sqlalchemy.sql import func, select
from datetime import datetime, timedelta

stmt = select([
    func.date_trunc('month', TrackingEntry.resource_id).label('when'),
    func.count(func.nullif(TrackingEntry.resource_id != 1, True)).label('res1'),
    func.count(func.nullif(TrackingEntry.resource_id != 2, True)).label('res2')
    ],
    group_by=[func.date_trunc('month', TrackingEntry.access_datetime), ])

Considering the outer select statement I have no idea how to build it, my guess is something like::

outer = select([
        func.distinct(func.date_trunc('month', ?)).label('date'),
        func.coalesce(?.res1, 0).label('res1'),
        func.coalesce(?.res2, 0).label('res2')
    ],
    from_obj=[
        func.generate_series(
                datetime.now(),
                datetime.now() + timedelta(days=365),
                timedelta(days=1)
            ).label(x)
    ])

Then I suppose I have to link those statements together without using foreign keys::

outer.outerjoin(stmt???).??(func.date_trunc('month', ?.?), ?.when)

Anyone got any suggestions or even better a solution?

http://pastie.org/994367

+1  A: 

not a full answer but when you want to join select() objects together they have a ".c." attribute, they effectively gain the same interface as the Table itself. so

s1 = select(...)
s2 = select(...)

s3 = select([s1,s2]).select_from(s1.join(s2, s1.c.foo==s2.c.bar))

The same applies for functions

select ([func.foo(s1.c.x)]).select_from(s1.join(s2, ...))
zzzeek
Thanks, I've solved it now. Running postmaster in debug mode made it alot easier seeing what the resulting queries actually looked like, helped me figure out where the issues where. I also had to use .alias(somename) on one of the selects, postgresql didn't enjoy the anonymous naming.
Torkel