I am using SQLAlchemy ORM and trying to figure out how to produce a PostgreSQL query like the following:
SELECT resources.*
FROM histories, jsonb_array_elements_text(histories.reported_resources) as report_resource_name
JOIN resources ON resources.resource_name = report_resource_name
WHERE histories.id = :id
So far I got this:
query = (
select([
Resource
])
.select_from(
History,
func.jsonb_array_elements(History.reported_resources).alias('report_resource_name'))
.join(Resource, Resource.resource_name == text('report_resource_name'))
.where(History.id = 1)
)
But the error says:
InvalidRequestError: Can’t determine which FROM clause to join from, there are multiple FROMS which can join to this entity. Please use the .select_from() method to establish an explicit left side, as well as providing an explicit ON clause if not present already to help resolve the ambiguity.
How can I join the resources table ON the jsonb_array_elements
result in .select_from()
using SQLAlchemey?
Minimum model table and input data like following:
class History(Base):
__tablename__ = 'histories'
id = Column(Integer, primary_key=True)
reported_resources = Column(JSONB)
class Resource(Base):
__tablename__ = 'resources'
id = Column(Integer, primary_key=True)
resource_name = Column(String)
Resource
id | resource_name
--------
1 | machine1
2 | machine2
3 | operator1
4 | operator4
History
id | reported_resources
-------
1 | ['machine2', 'operator4']
2
Answers
I am not fluid with the ORM dialect, but it should help to rewrite your SQL statement as:
(The
LATERAL
keyword being optional in this case.)See:
I am just converting the query suggested by @Erwin Brandstetter
in his answer.
The following code generates this query, I do a join on
true
as SQLAlchemy does not have a native cross join (feel free to correct me)Here is a complete example running on SQLAlchemy 2.0.
Output