Запрос выбора чибиса с несколькими соединениями и несколькими подсчетами

#peewee

Вопрос:

Я пытался написать запрос peewee select, который приводит к таблице с 2 подсчетами (один для количества призов, связанных с лотереей, и для количества пакетов, связанных с лотереей), а также полями в модели лотереи.

Мне удалось написать запросы select с рабочим количеством 1 (см. Ниже), а затем мне пришлось преобразовать выбранные модели в списки и присоединиться к ним вручную (что, по-моему, очень банально).

Мне удалось написать запрос select, в котором были объединены результаты, но это умножило бы количество пакетов на количество призов (с тех пор я потерял этот запрос).

Я также попытался использовать .switch(лотерея), но мне с этим не повезло.

 query1 = (Lottery.select(Lottery,fn.count(Package.id).alias('packages'))  .join(LotteryPackage)  .join(Package)  .order_by(Lottery.id)  .group_by(Lottery)  .dicts())  query2 = (Lottery.select(Lottery.id.alias('lotteryID'), fn.count(Prize.id).alias('prizes'))  .join(LotteryPrize)  .join(Prize)  .group_by(Lottery)  .order_by(Lottery.id)  .dicts())  lottery = list(query1) query3 = list(query2)  for x in range(len(lottery)):  lottery[x]['prizes'] = query3[x]['prizes']  

Хотя приведенный выше код работает, есть ли более чистый способ написать этот запрос?

Ответ №1:

Лучше всего сделать это с помощью подзапросов.

 # Create query which gets lottery id and count of packages. L1 = Lottery.alias() subq1 = (L1  .select(L1.id, fn.COUNT(LotteryPackage.package).alias('packages'))  .join(LotteryPackage, JOIN.LEFT_OUTER)  .group_by(L1.id))  # Create query which gets lottery id and count of prizes. L2 = Lottery.alias() subq2 = (L2  .select(L2.id, fn.COUNT(LotteryPrize.prize).alias('prizes'))  .join(LotteryPrize, JOIN.LEFT_OUTER)  .group_by(L2.id))  # Select from lottery, joining on each subquery and returning # the counts. query = (Lottery  .select(Lottery, subq1.c.packages, subq2.c.prizes)  .join(subq1, on=(Lottery.id == subq1.c.id))  .join(subq2, on=(Lottery.id == subq2.c.id))  .order_by(Lottery.name))  for row in query.objects():  print(row.name, row.packages, row.prizes)  

Комментарии:

1. Ах! Большое вам спасибо!

2. этот фрагмент-подарок, который продолжает дарить! 🙂