Виберіть окремі значення з поля таблиці


104

Я з усіх сил намагаюся обернути голову навколо ORM Джанго. Що я хочу зробити, це отримати список різних значень у полі на моїй таблиці .... еквівалент одного з наступних:

SELECT DISTINCT myfieldname FROM mytable

(або альтернативно)

SELECT myfieldname FROM mytable GROUP BY myfieldname

Принаймні, я хотів би зробити це способом Django, перш ніж вдаватися до сирої sql. Наприклад, з таблицею:

ід, вулиця, місто

1, Головна вулиця, Халл

2, Інша вулиця, Халл

3, Біблейський шлях, Лестер

4, Інший шлях, Лестер

5, Висока вулиця, Лондідіум

Я хотів би отримати:

Халл, Лестер, Лондідіум.

Відповіді:


203

Скажіть, що ваша модель "Магазин"

class Shop(models.Model):
    street = models.CharField(max_length=150)
    city = models.CharField(max_length=150)

    # some of your models may have explicit ordering
    class Meta:
        ordering = ('city')

Оскільки у вас може бути встановлений атрибут Metaкласу ordering, ви можете order_by()без параметрів очистити будь-яке замовлення під час використання distinct(). Дивіться документацію під order_by()

Якщо ви не хочете, щоб будь-яке замовлення було застосовано до запиту, навіть не за замовчуванням, зателефонуйте order_by () без параметрів.

і distinct()в примітці, де в ній обговорюються проблеми використання distinct()із замовленням.

Для запиту вашої БД вам просто потрібно зателефонувати:

models.Shop.objects.order_by().values('city').distinct()

Він повертає словник

або

models.Shop.objects.order_by().values_list('city').distinct()

Цей повертає те, ValuesListQuerySetщо ви можете передавати list. Ви можете також додати flat=Trueдо values_listвирівнюватися результати.

Дивіться також: Отримуйте відмінні значення Queryset за полями


29
Насправді це працює. Однак! Я не міг змусити його працювати на всіх своїх моделях. Weidly, це працювало на деяких, але не на інших. Для тих, у кого мета-замовлення, це не працює. Отже, ви повинні спочатку очистити замовлення на наборі запитів. models.Shop.objects.order_by (). values ​​('city'). razloct ()
alj

2
Важливо зазначити, що values_listнасправді список не повертається. Він повертає щось на зразок набору запитів. Мені здається корисним завжди використовувати list () навколо викликів value_list.
dheerosaur

8
values_listповертає ValuesListQuerySet, який є ітератором. Передавання списку може бути зручним, але також може вражати ефективність, коли всі рядки повинні бути оцінені відразу, особливо з великими наборами даних.
Петро Кільчук

3
Meta: ordering = ()«Особливість» Джанго ОРЗ і objects.distinct()VS. objects.ordering().distinct()викликає у нас годин плутанини. На цьому продукті має бути попереджувальна наклейка щодо безпеки споживачів;) Ми можемо запровадити політику без атрибутів мета-замовлення, щоб запобігти подряпини голови в майбутньому.
варильні панелі

Ви можете вимкнути Metaклас orderingі вирішити проблеми distinct, використовуючи order_by()без параметрів. Це в документах API QuerySet у розділі order_by()" Якщо ви не хочете, щоб до запиту було застосовано жодне замовлення, навіть не замовлення за замовчуванням, дзвоніть order_by()без параметрів ".
Марк Мікофський,

11

У доповненні до ще дуже відповідного відповіді jujule , я вважаю , це дуже важливо також знати про наслідки order_by()на distinct("field_name")запитах. Це, однак, лише функція Postgres!

Якщо ви використовуєте Postgres і якщо ви визначаєте ім'я поля, для якого запит має бути виразним, то order_by()потрібно починати з того самого імені поля (або імені поля) у тій же послідовності (згодом може бути більше полів).

Примітка

Коли ви вказуєте імена полів, ви повинні вказати order_by () у QuerySet, а поля в order_by () повинні починатися з полів у різних (), у тому ж порядку.

Наприклад, SELECT DISTINCT ON (a) дає вам перший рядок для кожного значення у стовпці a. Якщо ви не вказали замовлення, ви отримаєте деякий довільний рядок.

Якщо ви хочете, наприклад, витягнути список міст, в яких ви знаєте магазини, приклад жужулю повинен бути адаптований до цього:

# returns an iterable Queryset of cities.
models.Shop.objects.order_by('city').values_list('city', flat=True).distinct('city')  

2

Прикладом:

# select distinct code from Platform where id in ( select platform__id from Build where product=p)
pl_ids = Build.objects.values('platform__id').filter(product=p)
platforms = Platform.objects.values_list('code', flat=True).filter(id__in=pl_ids).distinct('code')
platforms = list(platforms) if platforms else []
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.