Что я пытаюсь сделать:
У меня есть 3 таблицы в Postgres БД.
user
-----------------------
user_id name age
-----------------------
001 Alice 25
002 Bob 32
003 Colin 31
004 Danny 40
laundry_task
-----------------------------
task_id user_id completed
-----------------------------
101 001 true
102 003 false
103 001 true
cooking_task
-----------------------------
task_id user_id completed
-----------------------------
201 001 true
202 002 true
203 003 false
Мне нужна SQLAlchemy, чтобы вернуть меня список кортежей, такой что:
[(001, 2, 1), (002, 0, 1)]
, где кортежи состоят из:
0) user_id
1) number_of_times_laundry_task_completed
2 ) number_of_times_cooking_task_completed
ИЛИ
[(001, 3), (002, 1)]
, где кортежи состоят из:
0) user_id
1) sum_of_times_boths_tasks_completed
Мне нужно это в одном запросе. (подзапросы в порядке)
Если в 1 из таблиц не назначены задачи , completed
count должен быть установлен в 0. Если в обеих таблицах нет назначенных задач, кортеж должен либо выглядеть как (004, 0, 0)
(или (004, 0)
), либо вообще отсутствовать в списке.
Как это выглядит в 2 запросах:
laundry_tasks = (
session.query(LaundryTask.user_id, func.count(LaundryTask.completed))
.filter(LaundryTask.completed == True)
.group_by(LaundryTask.user_id)
.all()
) # Results in [(001, 2)]
cooking_tasks = (
session.query(CookingTask.user_id, func.count(CookingTask.completed))
.filter(CookingTask.completed == True)
.group_by(CookingTask.user_id)
.all()
) # Results in [(001, 1), (002, 1)]
# Add some Python parsing to merge two lists of tuples into the needed format...
То, что я пробовал и вроде работало (но не совсем):
Подзапросы:
laundry_tasks_query = (
select([LaundryTask.user_id, func.count(LaundryTask.completed)])
.where(LaundryTask.completed == True)
.group_by(LaundryTask.user_id)
)
cooking_tasks_query = (
select([CookingTask.user_id, func.count(CookingTask.completed)])
.where(CookingTask.completed == True)
.group_by(CookingTask.user_id)
)
final_query = laundry_tasks_query.union(cooking_tasks_query).alias('completed_tasks')
completed_tasks = session.query(final_query).all()
Результат: completed_tasks = [(001, 2), (001, 1), (002, 1)]
Не уверен, есть ли способ до group_by
на union
до выполнения запроса, все мои попытки закончились Exception
с.
То, что я пробовал и не работало:
Сложить все в один запрос.
completed_tasks = (
session.query(
User.user_id, func.count(LaundryTask.completed), func.count(CookingTask.completed)
)
.filter(LaundryTask.completed == True)
.filter(CookingTask.completed == True)
.group_by(User.user_id)
.all()
)
Я знаю, наивно и, как и ожидалось, возвращает какую-то ерунду, ака [(001, magic_number, magic_number), (002, magic_number, magic_number), (003, magic_number, magic_number), (004, magic_number, magic_number)]
, где magic_number
- это то же целое число.
Если есть какие-либо другие способы получения нужного мне результата, я более чем открыт для предложений. Любая помощь приветствуется.