@vityaba3

Как одним запросом получить из БД уникальные данные по каждому столбцу (Django ORM)?

Мне нужно получить УНИКАЛЬНЫЕ данные из КАЖДОГО столбца
У меня есть список полей:
MY_FIELDS = ['id', 'created', 'И_еще_28']

Мой УЖАСНО НЕЭФФЕКТИВНЫЙ код, который дает правильный результат
qs = Sheets.objects.all()
v = []
v += [list(qs.values(v).distinct()) for v in MY_FIELDS]


Я получаю то, что мне нужно.... Но какой ценой? (28 запросов это больно)
Подскажите, как из этого сделать один запрос....
Вот так выдает неуникальные данные по КАЖДОМУ столбцу (пробовал)
qs = Sheets.objects.all().values(*MY_FIELDS).distinct()
  • Вопрос задан
  • 249 просмотров
Решения вопроса 2
ScriptKiddo
@ScriptKiddo
result = None
for field in MY_FIELDS:
    query = Sheets.objects.all().annotate(
        field_name=Value(field),
        field_value=F(field),
    ).values(
        'field_name',
        'field_value'
    ).distinct()
    if result is None:
        result = query
    else:
        result = result.union(query, all=True)

print(result.values())


Через explain посмотрите, сканируется ли таблица по количеству запросов distinct?
Ответ написан
@vityaba3 Автор вопроса
На SO @willeM_ Van Onsem дал такой ответ:


Your second approach does produce unique values, but these are unique combinations. So if there are 10 fields with each 5 values, that already can result in at most 510 results, so it scales dramatically.

But the good news is, we can solve this, by aggregating all columns into distinct lists. Indeed, with ArrayAgg [Django-doc]:

MY_FIELDS = ['id', 'created', 'And_more_28']

from django.contrib.postgres.aggregates import ArrayAgg

qs = Sheets.objects.aggregate(
    **{'values_{f}': ArrayAgg('f', distinct=True) for f in MY_FIELDS}
)
v = [qs[f'values_{f}'] for f in MY_FIELDS]


This will produce lists of distinct values for each column, and all in one single query.


Все еще не понятно, но выглядит проще....
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы