Объект Django Q добавляет лишнее - IS NOT NULL

для приведенного ниже необработанного запроса я хочу построить запрос Django ORM

Select * from employee 
WHERE (address_id is not null OR address_id<>'*')
    AND (xyz_id is null OR xyz_id='*')
    AND (abc_id is null OR abc_id='*')

Так что я построил ORM запрос следующим образом

data = Employee.objects.filter(~Q(address_id="23") | Q(address_id__isnull=False),
                            Q(xyz_id__isnull=False) | Q(xyz_id='*'),
                            Q(abc_id__isnull=True) | Q(abc_id=‘*’))

и когда я печатаю запрос, он отображается как показано ниже

SELECT "employee". "id", "employee". "xyz_id", "employee". "abc_id" FROM "employee" WHERE ((NOT ("employee". "address_id" = 23 AND "employee". "address_id" IS NOT NULL) OR "employee". "address_id" IS NOT NULL) AND ("employee". "xyz_id" IS NOT NULL OR "employee". "xyz_id" = *) AND ("employee". "abc_id" IS NULL OR "employee". "abc_id" = *))

.

Мой вопрос в том, почему объект Q в Django добавляет жирную строку в вышеуказанный сгенерированный запрос, который не решается для вышеуказанных необработанных sql критериев.

я использую Django 2.2 версии

Добрый совет

Если вы пишете Q(foo=bar), то неявное ограничение состоит в том, что foo не является NULL, если вы отрицаете это, то будет написано NOT (foo = bar), но если foo является NULL, то NOT (foo = bar) является NOT (NULL = bar), что является NULL, поэтому это будет отфильтровано из кверисета. что приведет к FALSE, тогда как для NULL можно ожидать, что это TRUE.

Чтобы убедиться, что ~Q(…) является полной противоположностью Q(…), следует добавить foo IS NOT NULL к условию.

В этом конкретном случае, однако, оптимизатор запроса, вероятно, действительно мог бы понять, что это не нужно из-за address_id IS NOT NULL позднее в запросе, но здесь, очевидно, оптимизатор не устраняет этот пункт.

Вернуться на верх