@borisalekseev
extra beginner junior python backend

Как заджоинить подзапрос?

Краткая инфа по моделям:
Bond - сложная связь многое ко многим, т.к. в ней записаны некоторые характеристики связи, она связывает модели Compound и Distinct.
Мне нужно получать в отчёте агррегированную инфу, и подцеплять к ней некоторые поля из таблицы Distinct. Джанго ни в какую хочет сначала делать группировку, а потом уже по оставшимся в результирующем наборе distinct_id подцеплять поля из Distinct. Я нашёл класс FilteredRelation в джанго, но он, как я понял, подходит только для фильтрации.

Что я имею поле чтения документации:
ORM
qs = Bond.objects.values('distinct_id').annotate(
detected_compounds=StringAgg(Cast('compound__pk', TextField()), delimiter='|'),
            cases=StringAgg(Cast('compound__cas__name', TextField()), delimiter='|'),
            names=StringAgg(Cast('compound__name__name', TextField()), delimiter='|'),
            iterations=StringAgg(Cast(
                'iterations_aggregate', TextField()), delimiter='|'),
            # processing_help
            compounds_count=Count('compound'),
    #
    description=FilteredRelation('distinct'),
    d = F('description__g31_1')
)
qs.query.__str__()

Он создаёт такой запрос:
SQL
SELECT "fts_bond"."distinct_id", STRING_AGG(("fts_bond"."compound_id")::text, | ) AS "detected_compounds", 
STRING_AGG(("compounds_synonym"."name")::text, | ) AS "cases", STRING_AGG((T5."name")::text, | ) AS "names", 
STRING_AGG(("fts_bond"."iterations_aggregate")::text, | ) AS "iterations",
COUNT("fts_bond"."compound_id") AS "compounds_count",
T6."g31_1" AS "d"
FROM "fts_bond"
INNER JOIN "compounds_compound" ON ("fts_bond"."compound_id" =  "compounds_compound"."id")
LEFT OUTER JOIN "compounds_synonym" ON ("compounds_compound"."cas_id" = "compounds_synonym"."id")
LEFT OUTER JOIN "compounds_synonym" T5 ON ("compounds_compound"."name_id" = T5."id") 
INNER JOIN "fts_distinct" T6 ON ("fts_bond"."distinct_id" = T6."id")
GROUP BY "fts_bond"."distinct_id", T6."g31_1

В этом запросе мне не нужна Т6 в том виде в которой она есть, мне нужно чтобы был запрос, выполняющий всё, кроме джоина T6, и к этому результату я буду джоинить нужные поля, по необходимым условиям и со своей, необходимой для моей бизнес-логики, группировкой. Мне нужно получить на django вот такой запрос:
SQL
SELECT "first_table".*, "second_table".my_field FROM (
    SELECT "fts_bond"."distinct_id", STRING_AGG(("fts_bond"."compound_id")::text, | ) AS "detected_compounds",  
    STRING_AGG(("compounds_synonym"."name")::text, | ) AS "cases", STRING_AGG((T5."name")::text, | ) AS "names", 
    STRING_AGG(("fts_bond"."iterations_aggregate")::text, | ) AS "iterations", COUNT("fts_bond"."compound_id") AS 
    "compounds_count", T6."g31_1" AS "d" FROM "fts_bond" INNER JOIN "compounds_compound" ON ("fts_bond"."compound_id" = 
    "compounds_compound"."id") LEFT OUTER JOIN "compounds_synonym" ON ("compounds_compound"."cas_id" = 
    "compounds_synonym"."id") LEFT OUTER JOIN "compounds_synonym" T5 ON ("compounds_compound"."name_id" = T5."id") 
    INNER JOIN "fts_distinct" T6 ON ("fts_bond"."distinct_id" = T6."id") GROUP BY "fts_bond"."distinct_id"
) AS "first_table"
INNER JOIN "my_table" AS "second_table" ON "second_table"."distinct_id" = "first_table"."distinct_id"

Как это сделать с помощью django? Нежелателен raw_sql, так как поля будут выбираться в интерфейсе.
В интернете нашёл похожие вопросы, но не дающие мне ответ.
  • Вопрос задан
  • 58 просмотров
Решения вопроса 1
@borisalekseev Автор вопроса
extra beginner junior python backend
Мною было принято решение брать два запроса и джоинить их по первичному ключу с помощью pandas, т.к. на нём в дальнейшем генериться эксель, ради которого всё происходит. Знакомые разрабы уровнем повыше тоже скептически отнеслись к моей необходимости в плане реализации её на django orm.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы