【问题标题】:Django in / not in queryDjango 在/不在查询中
【发布时间】:2023-03-05 09:56:01
【问题描述】:

我试图弄清楚如何在 django 中编写一个“不在”样式的查询。 例如,我正在考虑的查询结构如下所示。

select table1.* 
from table1
where table1.id not in 
(
  select table2.key_to_table1
  from table2 
  where table2.id = some_parm 
)

假设模型名为 table1 和 table2,django 语法会是什么样子?

【问题讨论】:

    标签: sql django


    【解决方案1】:
    table1.objects.exclude(id__in=
        table2.objects.filter(your_condition).values_list('id', flat=True))
    

    exclude 函数的工作方式类似于您所要求的 Not 运算符。属性flat = True 告诉table2 查询将value_list 作为一级列表返回。所以...最后你从 table2 中获得了一个IDs 的列表,你将让用户在table1 中定义条件,这将被排除函数拒绝。

    【讨论】:

    • 我也遇到了列表构造函数 [table2...] -> list(table2...) 为我工作的问题。
    • 更正:table1.objects.exclude(id__in = table2.objects.filter(your_condition).values_list('id', flat=True) )
    • 正在尝试使用此解决方案并遇到问题,所以如果它发生在其他人身上...Objs=Tbl1.objects.filter(...); IDs=Objs.values_list('id', flat=True); Objs.delete(); Tbl2.objects.filter(id__in=IDs') 这不起作用,因为 IDs 实际上是一个 QuerySet 对象。当我删除它源自的行时,它不再适用于其他查询。解决办法是Tbl2.objects.filter(id__in=list(IDs))——把它变成一个列表
    • 根据上下文,如果过滤器类似于“有 count(xx)==yy”,那么使用 annotate() 的速度会快 100 倍以上(timeit 给了我 1.0497902309998608 与 0.00514069400014705)
    【解决方案2】:

    使用这些模型:

    class table1(models.Model):
        field1 = models.CharField(max_length=10)      # a dummy field
    
    class table2(models.Model):
        key_to_table1 = models.ForeignKey(table1)
    

    你应该得到你想要的东西:

    table1.objects.exclude(table2=some_param)
    

    【讨论】:

    • 这仍然可能让您不必要地从数据库中提取大量记录。
    【解决方案3】:
    table1.objects.extra(where=["table1.id NOT IN (SELECT table2.key_to_table1 FROM table2 WHERE table2.id = some_parm)"])
    

    【讨论】:

      【解决方案4】:

      接受的答案是好的,但我将提供一种更可操作的新方法。

      from django.db.models import Q
      
      query = Q(id__in=table2.objects.filter(your_condition).values_list('id'))
      table1.objects.filter(~query)
      

      如果您使用主键,则无需调用 values_list()。

      Q() 对象上的“~”类似于“非”运算符。

      我想这种方法使代码更易于重用,并允许您通过将 Q() 对象存储在 var 上来执行“任何”类型的动态操作。

      【讨论】:

        【解决方案5】:

        您可以为 Django 查询编写自定义查找:

        来自documentation “让我们从一个简单的自定义查找开始。我们将编写一个自定义查找 ne,它与 exact 的作用相反。Author.objects.filter(name__ne='Jack' ) 将转换为 SQL:"author"."name" <> 'Jack'"

        from django.db.models import Lookup
        
        class NotEqual(Lookup):
            lookup_name = 'ne'
        
            def as_sql(self, compiler, connection):
                lhs, lhs_params = self.process_lhs(compiler, connection)
                rhs, rhs_params = self.process_rhs(compiler, connection)
                params = lhs_params + rhs_params
                return '%s <> %s' % (lhs, rhs), params
        

        【讨论】:

          【解决方案6】:
          [o1 for o1 in table1.objects.all() if o1.id not in [o2.id for o2 in table2.objects.filter(id=some_parm)]]
          

          或者更好

          not_in_ids = [obj.id for obj in table2.objects.filter(id=some_parm)]
          selected_objects = [obj for obj in table1.objects.iterator() if obj.id not in not_in_ids]
          

          【讨论】:

          • 遍历表中的每一行。 gg
          猜你喜欢
          • 1970-01-01
          • 2011-07-31
          • 2015-09-23
          • 1970-01-01
          • 2021-11-01
          • 2018-03-16
          • 1970-01-01
          • 2011-12-02
          • 1970-01-01
          相关资源
          最近更新 更多