#33477: Union Operator merges annotated values wrongfully
-------------------------------------+-------------------------------------
               Reporter:  Tobias     |          Owner:  nobody
  Maschek                            |
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  4.0
  layer (models, ORM)                |       Keywords:  annotation,
               Severity:  Normal     |  querysets, merging
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 Hi, maybe I'm doing something majorly incorrectly, but Django merges
 Querysets at least in an unexpected way.

 = Setup
 I have the following models:
 {{{
 class Employee(models.Model):
     name = models.CharField(max_length=64)

 class Shift(models.Model):
     employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
     start = models.DateTimeField()
     dur = models.DecimalField(max_digits=4, decimal_places=2, default=0)
 }}}

 = Querysets
 With
 {{{ employees_with_shifts =
 Employee.objects.filter(shift__start__range=(monday, monday +
 timedelta(weeks=1))).annotate(total=Sum('shift__dur')) }}}
 I can get all employees, that have at least one shift in the week
 containing the given monday, with the annotated total worktime.


 With
 {{{
 employees_without_shifts = Employee.objects.annotate(total=Value(0,
 IntegerField()))
     .exclude(shift__start__range=(monday, monday + timedelta(weeks=1)))
 }}}
 I get all employees without any shifts and on all objects is the total
 annotated with 0. So far, so good.

 = The Problem

 But if I'm now combining these two sets to `employees =
 employees_with_shifts | employees_without_shifts`, **the annotated total
 value is not any more zero** for all employees in
 `employees_without_shifts `, instead it's some sum of all shifts (ignoring
 the week). Even when the exclude statement is removed, it changes nothing.

 I suspect that Django combines these two Querysets before evaluating, and
 in the combination process the range gets thrown off.

 If I'm combining these two sets with `employees =
 sorted(chain(employees_with, employees_without), key=lambda instance:
 instance.id)` the annotated value is correct.

 Or do I use the union operator incorrectly?

-- 
Ticket URL: <https://code.djangoproject.com/ticket/33477>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/047.b4a1f02a857daf9ea04664cb7af45beb%40djangoproject.com.

Reply via email to