Python 在SQLAlchemy join子句中使用函数输出
我正在尝试将一小段SQL转换为sqlAlchemy ORM查询。SQL使用Postgres的Python 在SQLAlchemy join子句中使用函数输出,python,sql,postgresql,sqlalchemy,Python,Sql,Postgresql,Sqlalchemy,我正在尝试将一小段SQL转换为sqlAlchemy ORM查询。SQL使用Postgres的generate_series创建一组日期,我的目标是创建一组按其中一列分类的时间序列数组 表(简化)非常简单: counts: ----------------- count (Integer) day (Date) placeID (foreign key related to places) "counts_pkey" PRIMARY KEY (day, placeID) place
generate_series
创建一组日期,我的目标是创建一组按其中一列分类的时间序列数组
表(简化)非常简单:
counts:
-----------------
count (Integer)
day (Date)
placeID (foreign key related to places)
"counts_pkey" PRIMARY KEY (day, placeID)
places:
-----------------
id
name (varchar)
我所追求的输出是每个位置的计数时间序列,包括一天内未报告计数时的空值。例如,这将对应于超过四天的系列:
array_agg | name
-----------------+-------------------
{NULL,0,7,NULL} | A Place
{NULL,1,NULL,2} | Some other place
{5,NULL,3,NULL} | Yet another
通过对日期范围和地点进行交叉连接
,并将其与计数连接起来,我可以很容易地做到这一点:
SELECT array_agg(counts.count), places.name
FROM generate_series('2018-11-01', '2018-11-04', interval '1 days') as day
CROSS JOIN places
LEFT OUTER JOIN counts on counts.day = day.day AND counts.PlaceID = places.id
GROUP BY places.name;
我似乎不知道如何让SQLAlchemy做到这一点。经过大量的挖掘,我发现了一个几乎有效的方法:
date_list = select([column('generate_series')])\
.select_from(func.generate_series(backthen, today, '1 day'))\
.alias('date_list')
time_series = db.session.query(Place.name, func.array_agg(Count.count))\
.select_from(date_list)\
.outerjoin(Count, (Count.day == date_list.c.generate_series) & (Count.placeID == Place.id ))\
.group_by(Place.name)
这将为时间序列创建子选择,但会产生数据库错误:
表“places”有一个条目,但不能从查询的这一部分引用它
所以我的问题是:在sqlalchemy中你将如何做到这一点。此外,我也愿意接受这样一种观点,即这很困难,因为我使用SQL的方法非常顽固 问题在于,给定查询构造,SQLAlchemy会按照
选择。。。
从各地,
(…)AS date_列表左外部联接计数为。。。和计数。“placeID”=places.id
...
有两个来自
-列表项:位置
和连接。项目不能相互交叉引用1,因此在ON
-子句中由于places.id
而导致错误
SQLAlchemy不支持显式的交叉联接
,但另一方面,交叉联接
相当于(TRUE)上的内部联接。您还可以省略在子查询中包装函数表达式,并通过以下方式按原样使用它:
1:除了从
-项调用函数,或使用横向
date_list = func.generate_series(backthen, today, '1 day').alias('gen_day')
time_series = session.query(Place.name, func.array_agg(Count.count))\
.join(date_list, true())\
.outerjoin(Count, (Count.day == column('gen_day')) &
(Count.placeID == Place.id ))\
.group_by(Place.name)