Django mysql中的多对多关系和条件过滤

时间:2015-11-28 16:13:35

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

我在mysql下面的表格

enter image description here

以下是模型:

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语句     (lambda 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;

1 个答案:

答案 0 :(得分:-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.

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

testq = cube.objects.raw(your_sql)

然后,您可以检查testq或迭代它,提取您需要的数据。请参阅docs for Performing raw queries

希望有所帮助。