Возможен ли подобный подзапрос в 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')
    )
Вернуться на верх