Reputation: 745
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.
Upvotes: 1
Views: 1132
Reputation: 745
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.
Upvotes: 0