I'm trying to write the following SQL as a SQLAlchemy query:

SELECT COALESCE((
    SELECT client_id 
    FROM client_subclient_map m
    WHERE m.subclient_id = brands.client_id 
    LIMIT 1), 
    client_id)
FROM brands 
WHERE id = $1;

I've currently got function:

def client_subclient_map(self):
    return self.session.query(ClientSubclientMap).\
            filter(ClientSubclientMap.subclient_id==Brand.client_id).\
            limit(1).\
            subquery()

which creates the following subquery:

SELECT client_subclient_map.client_id, client_subclient_map.subclient_id 
FROM client_subclient_map, brands 
WHERE client_subclient_map.subclient_id = brands.client_id
LIMIT :param_1

and main function:

def top_client(self, brand_id):
    clientmap_alias = aliased(ClientSubclientMap, self.client_subclient_map())
    self.query = self.session.query(
                    func.coalesce(
                        clientmap_alias.client_id, Brand.client_id
                    )).\
                    filter(Brand.id==brand_id)
    print self.query
    return self

which creates query:

SELECT coalesce(:param_1, brands.client_id) AS coalesce_1 
FROM brands 
WHERE brands.id = :id_1

and then I just call

def get(self):
    return self.query.first()

The full query created by my functions when combined looks like:

SELECT coalesce(anon_1.client_id, brands.client_id) AS coalesce_1 
FROM (
    SELECT client_subclient_map.client_id AS client_id, 
        client_subclient_map.subclient_id AS subclient_id 
    FROM client_subclient_map, brands 
    WHERE client_subclient_map.subclient_id = brands.client_id
    LIMIT :param_1) AS anon_1, 
    brands 
WHERE brands.id = :id_1

which is wrong because the select subquery is happening in the wrong place, it needs to happen inside the coalesce function and not within the FROM clause to work.

I'm new to SQLAlchemy so it may well also be an issue elsewhere in my setup. I did have ForeignKey references on both client_id and subclient_id columns on the ClientSubclientMap table but there was some issue with both foreign keys referencing the same column Client.id so I removed the ClientSubclientMap.client foreign key reference.

sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join condition 
between parent/child tables on relationship ClientSubclientMap.subclients - 
there are multiple foreign key paths linking the tables.  Specify the 
'foreign_keys' argument, providing a list of those columns which should be 
counted as containing a foreign key reference to the parent table.
有帮助吗?

解决方案

Ended up having to rewrite the query as a JOIN with a CASE statement as a workaround.

def top_client(self, brand_id):
    self.query = self.session.query(case([(ClientSubclientMap.client_id==None, 
                                         Brand.client_id)],  
                                         else_=ClientSubclientMap.client_id))\
                    .outerjoin(ClientSubclientMap, 
                               Brand.client_id==ClientSubclientMap.subclient_id)\
                    .filter(Brand.id==brand_id)
    return self

which constructs the query:

SELECT 
    CASE 
        WHEN (client_subclient_map.client_id IS NULL) 
        THEN brands.client_id 
        ELSE client_subclient_map.client_id 
    END AS anon_1 
FROM brands 
    LEFT OUTER JOIN client_subclient_map 
        ON brands.client_id = client_subclient_map.subclient_id 
WHERE brands.id = :id_1

I'd still be interested to know how to do a nested SELECT statement inside a COALESCE function though if anyone can help.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top