【问题标题】:Django: Does chaining filter() functions result in the same SQL as using multiple kwargs?Django:链接 filter() 函数是否会产生与使用多个 kwargs 相同的 SQL?
【发布时间】:2012-06-17 02:10:53
【问题描述】:

在 Django 中,以下两个 sn-ps 是否产生相同的底层 SQL 查询?

qs = MyModel.objects.filter(group=1, type=2) 

qs = MyModel.objects.filter(group=1).filter(type=2) 

【问题讨论】:

    标签: django django-orm


    【解决方案1】:

    这实际上取决于是否存在连接或跨区查找,尤其是通过M2M 关系。例如

    >>> print User.objects.filter(groups__gt=1).filter(groups__lt=2).query
    SELECT "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "auth_user" INNER JOIN "auth_user_groups" ON ("auth_user"."id" = "auth_user_groups"."user_id") INNER JOIN "auth_user_groups" T4 ON ("auth_user"."id" = T4."user_id") WHERE ("auth_user_groups"."group_id" > 1  AND T4."group_id" < 2 )
    
    >>> print User.objects.filter(groups__gt=1, groups__lt=2).query
    SELECT "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "auth_user" INNER JOIN "auth_user_groups" ON ("auth_user"."id" = "auth_user_groups"."user_id") WHERE ("auth_user_groups"."group_id" < 2  AND "auth_user_groups"."group_id" > 1 )
    

    【讨论】:

    • 有趣。其中一个比另一个更有效吗?
    • @Ben 他们产生不同的 SQL,第二个连接较少,因此效率更高。此外,在构建示例中的一些复杂查询集时最好小心:它们可能会引入额外的连接。如果生成的查询相同,.filter().filter() 会生成另一个新的QuerySet,因此比单个.filter() 更慢且成本更高,但性能损失通常是微不足道的。
    【解决方案2】:

    是的

    更多关于QuerySets

    更多关于链接QuerySetfilters的文档:https://docs.djangoproject.com/en/dev/topics/db/queries/#chaining-filters

    提到的两个调用之间的区别

    不过,还是有一些区别。每个filter() 方法调用都会收到新的QuerySet 对象,所以执行此调用:

    qs = Model.objects.filter(group=1, type=2) 
    

    似乎比执行此调用更明智(就性能和您需要编写的代码量而言):

    qs = Model.objects.filter(group=1).filter(type=2)
    

    QuerySets 很懒

    正如本节的标题,仅仅返回QuerySet 并不意味着查询已经在数据库上执行。它只是用于执行查询的条件的容器。

    Documentation 说:

    QuerySets 是懒惰的——创建QuerySet 的行为不涉及任何数据库活动。您可以整天将过滤器堆叠在一起,直到QuerySet评估,Django 才会真正运行查询。

    【讨论】:

      【解决方案3】:

      两者都是相同的,我什至检查了正在生成的 sql 查询。它们是相同的。

      CreateCardTrack.objects.filter(email='vivek').filter(id=1)
      >>> connection.queries
      [{'time': '0.000', 'sql': u'SELECT `CreateCardTrack`.`id`, `CreateCardTrack`.`email`, `    CreateCardTrack`.`date` FROM `CreateCardTrack` WHERE (`CreateCardTrack`.`email` =     vivek.s  AND `CreateCardTrack`.`id` = 1 ) LIMIT 21'}]
      >>> CreateCardTrack.objects.filter(email='vivek.s',id=1)
      [<CreateCardTrack: CreateCardTrack object>]
      >>> #SELECT `CreateCardTrack`.`id`, `CreateCardTrack`.`email`, `CreateCardTrack`.`date` FROM `CreateCardTrack` WHERE (`CreateCardTrack`.`email` = vivek.s  AND `CreateCardTrack`.`id` = 1 ) LIMIT 21
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-05
        • 2021-08-27
        • 2014-05-28
        • 1970-01-01
        • 1970-01-01
        • 2011-12-31
        • 1970-01-01
        相关资源
        最近更新 更多