#mysql #django #django-models #django-queryset
#mysql #django #django-models #django-queryset
Вопрос:
У меня есть 2 querysets
, и я применяю union
к ним, но странная вещь, когда я использую only
, он выбирает все поля из базы данных, а когда я использую values
, он выбирает только заданные поля.
Это выбор всех полей из Physician
таблицы
doctors_models.Physician.objects.filter(
appointments__member=self.context['member']
).union(doctors_models.Physician.objects.filter(
appointments__booked_by=self.context['member']
)).only('id', 'name_prefix', 'first_name', 'middle_name', 'last_name', 'name_suffix')
НО
Это выбор только указанных полей из Physician
таблицы
doctors_models.Physician.objects.filter(
appointments__member=self.context['member']
).union(doctors_models.Physician.objects.filter(
appointments__booked_by=self.context['member']
)).values('id', 'name_prefix', 'first_name', 'middle_name', 'last_name', 'name_suffix')
Тем не менее, это также выбор только указанных полей, но почему я должен определять поля 2 раза.
doctors_models.Physician.objects.filter(
appointments__member=self.context['member']
).only('id', 'name_prefix', 'first_name', 'middle_name', 'last_name', 'name_suffix').union(
doctors_models.Physician.objects.filter(
appointments__booked_by=self.context['member']
).only('id', 'name_prefix', 'first_name', 'middle_name', 'last_name', 'name_suffix'))
Комментарии:
1. если у вас есть объединение, обе части должны иметь одинаковое количество полей
2. Он имеет те же поля.
3. Нет, это не так, поскольку ограничивает только поля, которые используются в запросе SELECT, также вы можете сделать это правильно в одном запросе, используя Q objects, Уиллем уже подробно объяснил это
Ответ №1:
Тем не менее, это также выбор только указанных полей, но почему я должен определять поля 2 раза?
Поскольку количество столбцов и их типы в обоих SELECT
операторах должны совпадать, как указано в документации по .union(…)
:
Передача разных моделей работает до тех пор, пока
SELECT
список одинаков во всехQuerySet
s (по крайней мере, типы, имена не имеют значения, если типы находятся в одном и том же порядке). В таких случаях вы должны использовать имена столбцов из первогоQuerySet
вQuerySet
методах, применяемых к результирующемуQuerySet
.
При этом, пожалуйста, не используйте .union(…)
в первую очередь для этого. Вы можете объединить два условия, обернув их в Q
объекты и объединив их с помощью «или«:
from django.db.models import Q
doctors_models.Physician.objects.filter(
Q(appointments__member=self.context['member']) |
Q(appointments__booked_by=self.context['member'])
).only('id', 'name_prefix', 'first_name', 'middle_name', 'last_name', 'name_suffix')
Кроме того, использование .only(…)
[Django-doc] или .defer(…)
[Django-doc] рекомендуется только для столбцов, содержащих большой объем данных. Для «маленьких» столбцов это часто не оказывает существенного влияния, и в случае, если вам позже понадобятся эти поля, это может даже привести к проблемам N 1.
Комментарии:
1. 1. ИЛИ запрос приведет к тому, что «индекс не будет использоваться», поэтому используйте объединение. 2. использование
only
так, чтобы оно не извлекало все ненужные поля. 3. Вы сказали, что объединение работает, когда столбцы в обоих запросах одинаковы, и они есть в моем запросе. Вы видите разные столбцы?2. @SHIVAMJINDAL: если вы отменяете оба столбца отдельно, обычно он будет использовать два индекса. Часто внутренняя база данных переписывает ее в ОБЪЕДИНЕНИЕ, но преимущество в том, что вы, таким образом, не пишете два
SELECT
оператора самостоятельно: orafaq.com/tuningguide/logical operators.html3. @Willen Это где-то написано, что mysql автоматически преобразует ИЛИ запрашивает в объединение
4. @SHIVAMJINDAL: хорошая база данных собирает статистику и составляет план запроса на основе статистики. Если вы создаете запрос, и база данных ожидает вернуть огромный кусок строк, она не будет использовать индекс, сканирование таблицы будет более эффективным (поскольку, даже если он использует индекс, позже ему придется сканировать, чтобы вернуть записи). План запросов основан на избирательности индексов . Таким образом, это означает, что если число различных
booked_by
s вappointments
отношении невелико, оно не будет использовать индекс.5. @SHIVAMJINDAL: таким образом, план запроса определяется не только запросом, но и количеством записей, которые база данных ожидает получить. Если избирательность равна 0.7, ожидается получение большого количества записей.