【问题标题】:Many to Many relationship AND conditions filtering in Django mysqlDjango mysql中的多对多关系和条件过滤
【发布时间】:2016-03-02 14:32:10
【问题描述】:

我在mysql中有下表

这是模型:

class cube(models.Model):
    pid = models.IntegerField()
    av = models.CharField(max_length=100)
    sid = models.IntegerField()
    st = models.IntegerField()

我想要实现的是我想知道 pid 的列表有

(sid=1,st>=5) and (sid=2,st>=7)

根据屏幕截图,这应该会从我的表中产生两个 pid - 3214 和 3215。 pid 3213 不满足条件,所以不返回。

我正在尝试以下方法来实现我在 View 中的要求:

查看代码:

testq=(cube.objects.filter((Q(sid='1') & Q(srt_gte="5")) & (Q(sid='2') & Q(srt_gte="7")))

也尝试以这种方式使用 lambda -

input = [{"sid":1,"st":5},{"sid":2,"st":7}]
queries = [Q(sid=i['sid'], st__gte=i['st']) for i in input]
sid_query = reduce(lambda x, y:  ________ , queries)

在上面的 lambda 中,我尝试使用 case 语句,例如 (λx: 1 如果查询其他 0 )

queryset=cube.objects.values_list('pid').filter(sid_query).annotate('pid') 

这不起作用:(

尝试了以下其他方式:

testq=cube.objects.filter(Q(sid__in=[1,2])& (Q(srt__gte=[5,7]))).annotate(c=Count('sid')).filter(c=2)

看来这是错误的。

无法弄清楚如何根据我的要求获得结果。

 List of pid's who has (sid=1,st>=5) and (sid=2,st>=7)

以下是该要求的等效 SQL:

select b.pid
from cube b
group by b.pid
having sum(case when (b.sid = 1) and (b.srt >= 5) then 1 else 0 end) > 0 AND
       sum(case when (b.sid = 2) and (b.srt >= 7) then 1 else 0 end) > 0;

【问题讨论】:

    标签: django python-3.x lambda django-views


    【解决方案1】:

    我相信您需要 OR 条件而不是 AND,并且您的第一个查询看起来几乎正确。你可以在你的 Q 对象中结合一些你的标准,让它更具可读性。

    testq = cube.objects.filter(Q(sid='1', st_gte="5") | Q(sid='2', st_gte="7"))
    

    AND 条件不起作用,因为数据库中的单个记录不能同时具有 sid=1sid=2(它们是两个单独的记录)。然后,您可以使用 testq.values_list('pid', flat=True) 来获取 pid 值。

    请注意,这会给你重复(你应该得到类似[3214, 3214, 3215, 3215]),所以你要么需要转换成一个集合:

    testq = set(testq)  # note: this will evaluate your query
    

    或在结果查询集上调用.distinct()

    testq = testq.distinct()  # testq is still a QuerySet object.
    

    如果您确定 SQL 查询返回您希望的结果,另一种方法是下拉并使用 raw 方法。

    testq = cube.objects.raw(your_sql)
    

    然后您可以检查 testq 或对其进行迭代以提取您需要的数据。见docs for Performing raw queries

    希望对您有所帮助。

    【讨论】:

    • 如果我使用'|'在过滤器中,它返回满足任一条件的行。所以,我会丢失所需的集,我试图根据我的输入集获得满足这两个条件的pid。这就是原因,我在按 pid 分组的 sql 查询中使用了 case 语句
    • @SathishPanduga 您是否考虑过使用 .raw 来运行您的查询?我刚刚用一个示例和这些文档的链接更新了我的答案。
    • 嗨布拉德,感谢更新!如果我使用原始查询,则很难对 20 个条件使用过滤器。尝试根据输入使用多个 case 语句,但我觉得有比 sql 查询中的多个语句更有效的方法。我要求对表使用 20 个过滤器.. 问题。
    猜你喜欢
    • 2020-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-08
    • 2021-03-19
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多