Ticket #2939: distinct-values-count-v4.patch
File distinct-values-count-v4.patch, 3.4 KB (added by , 17 years ago) |
---|
-
django/db/models/query.py
236 236 237 237 cursor = connection.cursor() 238 238 if self._distinct: 239 id_col = "%s.%s" % (connection.ops.quote_name(self.model._meta.db_table), 240 connection.ops.quote_name(self.model._meta.pk.column)) 241 cursor.execute("SELECT COUNT(DISTINCT(%s))" % id_col + sql, params) 239 columns = ', '.join(self._get_distinct_columns()) 240 cursor.execute("SELECT COUNT(DISTINCT(%s))" % columns + sql, params) 242 241 else: 243 242 cursor.execute("SELECT COUNT(*)" + sql, params) 244 243 count = cursor.fetchone()[0] … … 252 251 253 252 return count 254 253 254 def _get_distinct_columns(self): 255 "Returns distinct columns, used for count()" 256 return ["%s.%s" % (connection.ops.quote_name(self.model._meta.db_table), 257 connection.ops.quote_name(self.model._meta.pk.column))] 258 255 259 def get(self, *args, **kwargs): 256 260 "Performs the SELECT and returns a single object matching the given keyword arguments." 257 261 clone = self.filter(*args, **kwargs) … … 580 584 # select_related isn't supported in values(). 581 585 self._select_related = False 582 586 587 def _get_distinct_columns(self): 588 "Returns distinct columns, used for count()" 589 if not self._fields: 590 return super(ValuesQuerySet, self)._get_distinct_columns() 591 columns = [] 592 for f in self._fields: 593 if f in self._select: 594 columns.append(self._select[f]) 595 else: 596 columns.append('%s.%s' % 597 (connection.ops.quote_name(self.model._meta.db_table), 598 connection.ops.quote_name(self.model._meta.get_field(f, many_to_many=False).column))) 599 return columns 600 583 601 def iterator(self): 584 602 try: 603 if self._distinct: 604 self._order_by = [] 585 605 select, sql, params = self._get_sql_clause() 586 606 except EmptyResultSet: 587 607 raise StopIteration -
tests/modeltests/lookup/models.py
168 168 >>> list(Article.objects.filter(id=5).values()) == [{'id': 5, 'headline': 'Article 5', 'pub_date': datetime(2005, 8, 1, 9, 0)}] 169 169 True 170 170 171 # .values(*fields).distinct().count() will return the correct number of 172 # distinct records. 173 >>> Article.objects.values('pub_date').count() 174 7 175 >>> len(Article.objects.values('pub_date').distinct()) 176 5 177 >>> Article.objects.values('pub_date').distinct().count() 178 5 179 180 # And make sure it still works if no fields are passed: 181 >>> len(Article.objects.values().distinct()) 182 7 183 >>> Article.objects.values().distinct().count() 184 7 185 186 # And make sure you can count() distinct() fields that are added 187 # by extra(): 188 >>> Article.objects.extra(select={'poorhash':'SUBSTRING(MD5(lookup_article.headline) FROM 1 FOR 1)'}).values('poorhash').distinct().count() 189 6L 190 171 191 # Every DateField and DateTimeField creates get_next_by_FOO() and 172 192 # get_previous_by_FOO() methods. 173 193 # In the case of identical date values, these methods will use the ID as a