Мне нужно, чтобы мой запрос вернул мне общее количество товара (int) в сумке и общую сумму цены (десятичное число). В мешке может быть 0 овощей, но 3 фрукта, и наоборот, в нем могут быть предметы, но они могут быть бесплатными, а также он может быть пустым и иметь цену (цену самого мешка). Поэтому мы отфильтровываем только сумки с 0 товарами и 0 total_price в конце.
Лучшее, что я мог сделать, это четыре таких подзапроса:
Код: Выделить всё
query = select(Bag.id, Bag.purchase_datetime)
vegetable_price = select(func.sum(Vegetable.amount)).where(Vegetable.bag_id == Bag.id).scalar_subquery().label("vegetable_price_total")
vegetable_count = select(func.count(Vegetable.id)).where(Vegetable.bag_id == Bag.id).scalar_subquery().label("vegetable_count_total")
fruit_price = select(func.count(Fruit.id)).where(Fruit.bag_id == Bag.id).scalar_subquery().label("fruit_price_total")
fruit_count = select(func.count(Fruit.id)).where(Fruit.bag_id == Bag.id).scalar_subquery().label("fruit_count_total")
query = add_columns(vegetable_price, vegetable_count, fruit_price, fruit_count)
И, наконец, я складываю столбцы в объект, возвращаемый маршрутом, вот так:
Код: Выделить всё
result = session.execute(query.distinct())
for b in result:
yield BagObject(
id=b.id
item_count=(getattr(b, "vegetable_count_total", 0) or 0) + (getattr(b, "fruit_count_total", 0) or 0),
total_price=(getattr(b, "vegetable_price_total", 0) or 0) + (getattr(b, "fruit_price_total", 0) or 0),
)
Я пробовал другие вещи, такие как join, externaljoin. Но все они приводили к дублированию строк и умножению цены/item_count в конечном результате.
Подробнее здесь: https://stackoverflow.com/questions/790 ... same-table