【问题标题】:Is a subquery of this kind possible in django?在 django 中可以使用这种子查询吗?
【发布时间】:2021-11-23 16:29:43
【问题描述】:

在 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)

# you asked for it!
def get_whens(category_ordering, page_size):
    page_number = Ceil(Cast(F('row_number') * 1.0 /
                            page_size, output_field=FloatField()))

    return [
        When(
            category__name=c,
            then=(
                Cast(
                    (page_number * len(category_ordering) - len(category_ordering) +
                     category_ordering.index(c) + 1)  # real_page_number
                    *
                    page_size
                    -
                    page_size
                    +
                    F('row_number')
                    -
                    (
                        (page_number - 1)
                        *
                        page_size
                    ),
                    output_field=IntegerField()
                )
            )
        )
        for c in category_ordering
    ]



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')
)

最新

我认为这是不可能的。发现了一个类似的问题——How to write subquery in From clause in django ORM

我将不得不编写一个原始的 sql 查询。

我已对这张票添加了评论 - https://code.djangoproject.com/ticket/28333#comment:17

【问题讨论】:

  • Django 支持explicit subqueries。你能提供当前的查询和模型吗?
  • 是的,这是我所知道的子查询类型。他们在文档中提供的示例与这种情况不同。
  • 您要过滤的是 row_number 注释吗?
  • 不,我需要过滤 order_value 列。此列取决于 row_number 列。可调用的 get_whens 涉及的逻辑无关紧要,但涉及 row_number 列,你看。
  • 你能分享get_whens吗?窗口注解的使用方式可能会改变解决方案

标签: django


【解决方案1】:

我在这张票上添加了评论,这样我们就可以通过 django 的 ORM 解决这类问题 - 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')
    )

【讨论】:

    猜你喜欢
    • 2013-03-05
    • 1970-01-01
    • 1970-01-01
    • 2016-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 1970-01-01
    相关资源
    最近更新 更多