Я пытаюсь перевести довольно короткий фрагмент SQL в запрос sqlAlchemy ORM. SQL использует Postgres 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
Я могу сделать это довольно легко, взяв CROSS JOIN
в диапазоне дат и мест и соединив его с количеством:
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 сделать это. После долгих поисков я обнаружил старую ветку групп Google , которая почти работает, что приводит к этому:
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)
Это создает дополнительный выбор для временного ряда, но выдает ошибку базы данных:
Существует запись для таблицы "place", но на нее нельзя ссылаться из этой части запроса.
Итак, мой вопрос: как бы вы сделали это в sqlalchemy. Кроме того, я открыт для идеи, что это сложно, потому что мой подход с SQL является хладнокровным.