如何在sql-query的末尾向所有查询集添加过滤器?

时间:2018-11-26 13:45:57

标签: django database orm django-queryset

如果我在管理器中添加过滤器,则对数据库的sql查询将太长,因为我的过滤器将在sql-query的开始。

在应用所有其他过滤器和更改之后,我需要在最后运行此过滤器。

当前查询集:

links = Link.objects.all().filter_deleted()
links = links.filter(linkname='linkname', left_uuid__in=all_uuids)
links = links.filter(left_type='type')
links = links.values_list('left_uuid', 'right_uuid', 'right_type')
编译队列集后的

SQL查询:

SELECT "baseobj_link"."left_uuid", "baseobj_link"."right_uuid", "baseobj_link"."right_type_id"
FROM "baseobj_link"
WHERE (
    "baseobj_link"."id" IN (
        SELECT DISTINCT ON (U0."linkname", U0."left_uuid", U0."right_uuid") U0."id" AS Col1
        FROM "baseobj_link" U0
        WHERE U0."config_id" IN (2848)
        ORDER BY U0."linkname" ASC, U0."left_uuid" ASC, U0."right_uuid" ASC, U0."domain_level" ASC, U0."config_id" DESC, U0."is_deleted" DESC
    ) AND
    "baseobj_link"."is_deleted" = false AND
    "baseobj_link"."linkname" = 'linkname' AND
    "baseobj_link"."left_uuid" IN (
        SELECT V0."uuid" AS Col1
        FROM "structure_cgw" V0
        WHERE (
            V0."id" IN (
                SELECT DISTINCT ON (U0."uuid") U0."id" AS Col1
                FROM "structure_cgw" U0
                WHERE U0."config_id" IN (2848)
                ORDER BY U0."uuid" ASC, U0."domain_level" DESC, U0."config_id" DESC
            ) AND
            V0."is_deleted" = false
        )
    ) AND
    "baseobj_link"."left_type_id" = 6
);
args=(2848, False, 'linkname', 2848, False, 6)

filter_deleted()生成的部分:

"baseobj_link"."id" IN (
    SELECT DISTINCT ON (U0."linkname", U0."left_uuid", U0."right_uuid") U0."id" AS Col1
    FROM "baseobj_link" U0
    WHERE U0."config_id" IN (2848)
    ORDER BY U0."linkname" ASC, U0."left_uuid" ASC, U0."right_uuid" ASC, U0."domain_level" ASC, U0."config_id" DESC, U0."is_deleted" DESC
)

有必要在此模型的所有查询的末尾添加此代码,因此这不是一个简单的任务。

如何最有效地解决这个问题?

2 个答案:

答案 0 :(得分:1)

听起来像您正在尝试对子查询运行过滤器。因此,将您希望首先运行的所有代码放在子查询中。然后,在该查询结束后,在最后一个过滤器中运行您希望应用的过滤器。

会看起来像这样:

SELECT *
FROM    (
        SELECT "baseobj_link"."left_uuid", "baseobj_link"."right_uuid", "baseobj_link"."right_type_id"
        FROM "baseobj_link"
        WHERE
            "baseobj_link"."is_deleted" = false AND
            "baseobj_link"."linkname" = 'cgw_vhost' AND
            "baseobj_link"."left_uuid" IN (
                SELECT V0."uuid" AS Col1
                FROM "structure_cgw" V0
                WHERE (
                    V0."id" IN (
                        SELECT DISTINCT ON (U0."uuid") U0."id" AS Col1
                        FROM "structure_cgw" U0
                        WHERE U0."config_id" IN (2848)
                        ORDER BY U0."uuid" ASC, U0."domain_level" DESC, U0."config_id" DESC
                    ) AND
                    V0."is_deleted" = false
                )
            AND "baseobj_link"."left_type_id" = 6
        ) AS t1
WHERE t1.id IN (
    SELECT DISTINCT ON (U0."linkname", U0."left_uuid", U0."right_uuid") U0."id" AS Col1
    FROM "baseobj_link" U0
    WHERE U0."config_id" IN (2848)
    ORDER BY U0."linkname" ASC, U0."left_uuid" ASC, U0."right_uuid" ASC, U0."domain_level" ASC, U0."config_id" DESC, U0."is_deleted" DESC
)

从MYSQL documentation导出表上:

  

派生表是在查询FROM子句范围内生成表的表达式。例如,SELECT语句FROM子句中的子查询是派生表:

     

SELECT ... FROM (subquery) [AS] tbl_name ...

让我知道这是怎么实现的。

答案 1 :(得分:0)

Всвоеймоделиqueryset'адополнительнохранимquerysetбезfilter_deletedипереопределяемметод_filter_or_exоlude,чтоты Такжехранимфлагфильтрации,过滤器_filter_or_exclude,过滤器已删除。