Django에서 DISTINCT 개별 열을 선택 하시겠습니까?


93

SELECT * FROM...아래에 " " 가 아닌 Django에서 쿼리를 수행하는 방법이 있는지 궁금합니다 . SELECT DISTINCT columnName FROM ...대신 " "을 (를) 하려고합니다 .

특히 다음과 같은 모델이 있습니다.

class ProductOrder(models.Model):
   Product  = models.CharField(max_length=20, promary_key=True)
   Category = models.CharField(max_length=30)
   Rank = models.IntegerField()

어디는 Rank내에서 순위입니다 Category. 해당 범주 내의 각 순위에서 일부 작업을 수행하는 모든 범주를 반복 할 수 있기를 바랍니다.

먼저 시스템의 모든 카테고리 목록을 가져온 다음 해당 카테고리의 모든 제품을 쿼리하고 모든 카테고리가 처리 될 때까지 반복하고 싶습니다.

차라리 원시 SQL을 피하고 싶지만 거기에 가야한다면 괜찮을 것입니다. 전에 Django / Python에서 원시 SQL을 코딩 한 적이 없지만.

답변:


185

데이터베이스에서 고유 한 열 이름 목록을 가져 오는 한 가지 방법 distinct() 은와 함께 사용 하는 것입니다 values().

귀하의 경우 다음을 수행하여 고유 한 범주의 이름을 가져올 수 있습니다.

q = ProductOrder.objects.values('Category').distinct()
print q.query # See for yourself.

# The query would look something like
# SELECT DISTINCT "app_productorder"."category" FROM "app_productorder"

여기서 기억해야 할 몇 가지 사항이 있습니다. 첫째, 이것은 반환 ValuesQuerySet에서 다르게 작동하는가 QuerySet. say에 액세스하면 q(위) 의 첫 번째 요소가 의 인스턴스가 아닌 사전을 얻습니다 ProductOrder.

둘째, .NET Framework 사용에 대한 문서 의 경고 노트 를 읽는 것이 좋습니다 distinct(). 위의 예는 작동하지만 모든 조합 것 distinct()values()하지 않을 수 있습니다.

추신 : 모델의 필드에 소문자 이름 을 사용하는 것이 좋습니다 . 귀하의 경우 이것은 아래와 같이 모델을 다시 작성하는 것을 의미합니다.

class ProductOrder(models.Model):
    product  = models.CharField(max_length=20, primary_key=True)
    category = models.CharField(max_length=30)
    rank = models.IntegerField()

1
아래에 설명 된 방법은 이제 django 1.4에서 사용할 수 있으며 필드 인식 고유 한 ProductOrder 인스턴스가 필요한 경우
유용합니다.

61

사실은 아주 간단 당신은 PostgreSQL을 사용하는 경우 , 단지 사용 distinct(columns)( 문서 ).

Productorder.objects.all().distinct('category')

이 기능은 1.4 이후 Django에 포함되었습니다.


@lazerscience, @Manoj Govindan : 미안 해요, 당신 말이 맞아요. 그 기능을 추가하기 위해 Django를 패치 한 것 같습니다. 패치 링크를 추가했습니다
Wolph

3
이것은 현재 Django SVN에 있으며 Django 1.4에있을 것입니다
Will Hardy

14
참고 : PostgreSQL을 사용하지 않는 한 distinct ()에 인수를 제공 할 수 없습니다. 위의 허용 된 솔루션을 사용하는 것이 가장 좋습니다.
Mark Chackerian 2013

시험에서,이다 can_distinct_on_fields포스트 그레스 전용으로 표시되는
스카 일러 Saveland

3
플러스 1,하지만 all()여기에 필요하지 않습니다
안토니 Hatchkins

17

다른 답변은 괜찮지 만 Django에서 아무런 문제없이 DISTINCT 쿼리에서 얻을 수있는 값만 제공한다는 점에서 조금 더 깔끔합니다.

>>> set(ProductOrder.objects.values_list('category', flat=True))
{u'category1', u'category2', u'category3', u'category4'}

또는

>>> list(set(ProductOrder.objects.values_list('category', flat=True)))
[u'category1', u'category2', u'category3', u'category4']

그리고 PostgreSQL 없이도 작동합니다.

데이터베이스의 DISTINCT가 python보다 빠르다고 가정하면 .distinct ()를 사용하는 것보다 덜 효율적 set이지만 셸 주위를 노들 링하는 데는 좋습니다.


values_listDISTINCTSQL 쿼리에 넣지 않으므로 있는 경우 여러 값을 가져옵니다.
mehmet 2016-06-29

13

사용자는 해당 필드로 주문한 다음 구별합니다.

ProductOrder.objects.order_by('category').values_list('category', flat=True).distinct()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.