关于Django中的数据库操作API之distinct去重的一个误传

转载自http://www.360doc.com/content/18/0731/18/58287567_774731201.shtml

django提供的数据库操作API中的distinct()函数,了解SQL语句的读者都应该知道,DISTINCT关键字可以在select操作时去重。django里的这个distinct()函数也是这个功能,通常的用法是我们要取出一张表中的某一列的所有值,并且只取出不重复的,如果有重复的就只取出来一次,网络上几乎所有的对这个函数的使用例子对应的Python代码都如下:

 但是这样的用法往往达不到使用者的意图,可以来看一下网络上流传甚广的一个问答:
比如这个:http://bbs.csdn.net/topics/330006477
再比如这个:http://www.douban.com/group/topic/17856879/
这里其实说的都是一个例子,仔细看这个解答

—–
需要注意的是,这样返回的是一个字典的列表,而不是通常的 QuerySet
—
这样是过滤不掉的,这是个问题,还是有5个对象在里面,对结果使用len(obj)就知道没有任何变化,但是如果只作统计不重复数据的个数的话,还是准确的3个
obj=ClassName.objects.values(‘name’).distinct()
len(obj)=5
obj.count()=3
但是结果集中没有起到任何的过滤作用,此问题有待解决!!!!!

有理有据,让人很信服的认为distinct()函数没有实现其所描述的功能。真的是这样么?

在这里负责的告诉读者,上面的解释是错误的,distinct()具有去重功能是没有必要怀疑的,那为什么会出现上面的解释呢?因为他不知道distinct()函数有一个隐藏特性,当使用distinct()函数的时候,如果不使用order_by()函数做跟随,那么该函数会自动把当前表中的默认排序字段作为DISTINCT的一个列,所以上述问题出现的原因是因为他没有使用order_by(‘name’)来屏蔽distinct()的那个特性,从而得出的distinct结果并不是仅仅以name一个列作为参数的,而是以id+name两列的值作为distinct参数,可以看到id列里面的值全部都是唯一值,所以得出来的结果必然是以id列的值为标准的,这也就是的原因,而如果想要实现上述例子中楼主的需求,正确的代码写法是:

Python

d1 = models.Device.objects.values('business_id').distinct().order_by('business_id')

在1.4+版本的django中distinct()函数可以传入一个参数,从而省去了后面跟加一个order_by()函数的必要,但是这也需要你的数据库支持Postgresql,否则还是无效的。

原文地址:https://www.cnblogs.com/jiangxiaobo/p/11646179.html