Возможен ли подобный подзапрос в django?
В sql я могу сделать что-то вроде этого -
select a, b, c from (
select a, b, c from table_a
)
where a = something
Возможно ли это в django? Я использовал только подзапросы такого типа, когда первичный ключ подзапроса, например, сопоставляется со столбцом строки в родительском запросе. Но в данном случае мне это не нужно.
Вот контекст.
У меня есть запрос, в котором есть аннотированный столбец, использующий оконную рамку. Такое выражение не может быть включено в предложение WHERE, поскольку sql сначала оценивает предложение where. Поэтому необходимо сначала выполнить этот запрос как подзапрос, а затем использовать результат как собственную таблицу. На этом родительском запросе я могу затем выполнить фильтрацию.
Смотрите - https://learnsql.com/blog/window-functions-not-allowed-in-where/
class Item(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
q = (
Item
.objects
.annotate(
row_number=Window(
expression=RowNumber(),
partition_by=[F('category_id')]
)
)
.annotate(
order_value=Case(*get_whens(category_ordering, page_size))
)
.order_by('order_value')
)
Я добавил комментарий к этому тикету, чтобы мы могли решить подобную проблему через ORM от django - https://code.djangoproject.com/ticket/28333#comment:17.
На данный момент я решил проблему с помощью этого стороннего пакета - https://github.com/dimagi/django-cte. Он предлагает общие табличные выражения через django orm.
Мое решение основано на базовом примере, который дает пакет.
q = (
Item
.objects
.annotate(
row_number=Window(
expression=RowNumber(),
partition_by=[F('category_id')]
)
)
.annotate(
order_value=Case(*get_whens(category_ordering, page_size))
)
.order_by('order_value')
)
cte = With(q)
actual_queryset = (
cte
.join(Item, pk=cte.col.pk)
.with_cte(cte)
.annotate(order_value=cte.col.order_value)
.order_by('order_value')
)