I wrote an SQL query to create a view for the database I'm working on and the query works as expected:
CREATE OR REPLACE VIEW public.current_model
AS SELECT pm.model_id,
mp.name,
ga.pit,
pm.description,
pm.created_datetime,
pm.folder_full_path,
pm.status
FROM prediction_model pm
JOIN material_property mp ON pm.property_id = mp.auto_id
JOIN geographic_applicability ga ON ga.model_id = pm.auto_id
WHERE pm.status::text <> 'INACTIVE'::text AND (pm.created_datetime IN ( SELECT max(pm2.created_datetime) AS max
FROM prediction_model pm2
JOIN geographic_applicability ga2 ON ga2.model_id = pm2.auto_id
JOIN material_property mp2 ON pm2.property_id = mp2.auto_id
GROUP BY mp2.name, ga2.pit));
Now I need to add this view to the sqlalchemy schema for the database. I have successfully implemented couple other views, but this one gets me lost (mind you, I have almost no previous sqlalchemy experience). This is what I have come up with so far:
@classmethod
def current_model_view(cls):
j1 = cls.prediction_model.join(cls.material_property,
cls.prediction_model.c.property_id == cls.material_property.c.auto_id)
j2 = j1.join(cls.geographic_applicability,
cls.prediction_model.c.auto_id == cls.geographic_applicability.c.model_id)
s1 = cls.prediction_model.join(cls.geographic_applicability,
cls.geographic_applicability.c.model_id == cls.prediction_model.c.auto_id)
s2 = s1.join(cls.material_property, cls.prediction_model.c.property_id == cls.material_property.c.auto_id)
max_date = select(max(cls.prediction_model.c.created_datetime)).\
select_from(s2).group_by(cls.material_property.c.name, cls.geographic_applicability.c.pit)
view_selectable = select([cls.material_property.c.name,
cls.geographic_applicability.c.pit,
cls.prediction_model.c.description,
cls.prediction_model.c.created_datetime,
cls.prediction_model.c.folder_full_path,
cls.prediction_model.c.status]).\
select_from(j2).\
where(and_(not_(cls.prediction_model.c.status == 'INACTIVE'),
cls.prediction_model.c.created_datetime.in_(max_date)))
return view_selectable
But this gives me the following error:
Traceback (most recent call last):
File "C:/python/mhi_versionist/mhi_versionist/data_base/tracker_database_schema.py", line 320, in <module>
create_view('current_model', ModelDB.current_model_view(), ModelDB.model_db_meta)
File "C:/python/mhi_versionist/mhi_versionist/data_base/tracker_database_schema.py", line 154, in current_model_view
max_date = select(max(cls.prediction_model.c.created_datetime)).\
File "C:\python\mhi_versionist\venv2\lib\site-packages\sqlalchemy\sql\operators.py", line 432, in __getitem__
return self.operate(getitem, index)
File "C:\python\mhi_versionist\venv2\lib\site-packages\sqlalchemy\sql\elements.py", line 762, in operate
return op(self.comparator, *other, **kwargs)
File "C:\python\mhi_versionist\venv2\lib\site-packages\sqlalchemy\sql\operators.py", line 432, in __getitem__
return self.operate(getitem, index)
File "<string>", line 1, in <lambda>
File "C:\python\mhi_versionist\venv2\lib\site-packages\sqlalchemy\sql\type_api.py", line 67, in operate
return o[0](self.expr, op, *(other + o[1:]), **kwargs)
File "C:\python\mhi_versionist\venv2\lib\site-packages\sqlalchemy\sql\default_comparator.py", line 237, in _getitem_impl
_unsupported_impl(expr, op, other, **kw)
File "C:\python\mhi_versionist\venv2\lib\site-packages\sqlalchemy\sql\default_comparator.py", line 241, in _unsupported_impl
raise NotImplementedError(
NotImplementedError: Operator 'getitem' is not supported on this expression
Not sure how to solve this.
It looks like in the following line:
max_date = select(max(cls.prediction_model.c.created_datetime)).\
you're using Python's max
function, rather than passing the sql max
function. Can you try using max
from sqlalchemy
instead? It sits in the func
module. So write:
max_date = select([func.max(cls.prediction_model.c.created_datetime)]).\
Note that you also need to use a list in your select
query, hence the added [ ]
.
On another note, if the ForeignKey
relationships have been defined correctly in your table definitions, you don't need to tell sqlalchemy
explicitely how to do the join. So in that case you could get away with something like:
j1 = cls.prediction_model.join(cls.material_property).join(cls.geographic_applicability)
s1 = cls.prediction_model.join(cls.geographic_applicability).join(cls.material_property)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.