In my 10 years playing with Django i found a few bugs, but i never had to 
fall back to a raw SQL query. Fiddling with Django for almost a full day 
now im out of ideas except of asking for help here:

I have an organizer app with days containing shifts and people working 
those shifts (M2M). There also are supervisors for each day that are 
directly stored on the day (M2M). For the user stats i want to see who has 
how many shifts. For speed reasons i WANT to handle this with only one 
query. Here is the query i started with:

assigned_to = self.shifts.filter(day_id=OuterRef('id')).order_by()
days = Day.data.filter(date__range=(start, end)).distinct().annotate(
    assigned_shifts=Count(
        Subquery(assigned_to.values('id'))
    )).annotate(
    assigned_pl=Max(Case(
        When(production_managers=self, then=1),
        default=0, output_field=models.IntegerField(),
        distinct=True
    ))).annotate(
    assigned_tl=Max(Case(
        When(day_managers=self, then=1),
        default=0, output_field=models.IntegerField(), distinct=True
    ))).annotate(
    assigned_al=Max(Case(
        When(managers=self, then=1),
        default=0, output_field=models.IntegerField(), distinct=True
    ))).annotate(
    assigned_cash=Max(Case(
        When(cash_managers=self, then=1),
        default=0, output_field=models.IntegerField(), distinct=True
    ))).order_by()


This is giving me an SQL error "more than one row returned by a subquery 
used as an expression", without the subquery i was getting false values - 
probably because the grouping didnt work out as its supposed to. Turns out 
there is a warning in the docs and a very old ticket 
(https://code.djangoproject.com/ticket/10060) warning about this exact 
scenario, but somehow i dont get the subquery to work like it should.

The final and a lil simplified SQL looks like this:

days = Day.data.raw("""
    SELECT distinct
      "events_day"."id","events_day"."date",
      (select count(*) 
       from events_shift 
       left outer join events_shift_employees 
       on events_shift_employees.shift_id = events_shift.id 
       where events_shift_employees.user_id = {user_id} and 
       events_shift.day_id = events_day.id and 
       events_shift.deleted is null) AS "assigned_shifts",
      Max(CASE WHEN"events_day_production_managers"."user_id"={user_id} THEN 1 
ELSE 0 END)AS"assigned_pl",
      Max(CASE WHEN"events_day_day_managers"."user_id"={user_id} THEN 1 ELSE 0 
END)AS"assigned_tl",
      Max(CASE WHEN"events_day_managers"."user_id"={user_id} THEN 1 ELSE 0 
END)AS"assigned_al",
      max(CASE WHEN"events_day_cash_managers"."user_id"={user_id} THEN 1 ELSE 0 
END)AS"assigned_cash"
    FROM"events_day"
    LEFT JOIN"events_shift"ON("events_day"."id"="events_shift"."day_id")
    LEFT 
JOIN"events_shift_employees"ON("events_shift"."id"="events_shift_employees"."shift_id")
    LEFT 
JOIN"events_day_production_managers"ON("events_day"."id"="events_day_production_managers"."day_id")
    LEFT 
JOIN"events_day_day_managers"ON("events_day"."id"="events_day_day_managers"."day_id")
    LEFT 
JOIN"events_day_managers"ON("events_day"."id"="events_day_managers"."day_id")
    LEFT 
JOIN"events_day_cash_managers"ON("events_day"."id"="events_day_cash_managers"."day_id")
    WHERE("events_day"."deleted"IS NULL AND"events_day"."date" BETWEEN 
'{start}' AND '{end}')
    GROUP BY "events_day"."id"
    ORDER BY"events_day"."date"DESC
""".format(**{
    'user_id': self.id,
    'start': start,
    'end': end
}))



I could need a lil hand here in achiving the SELECT COUNT(*) in line 4 
rather then the Count(Subquery()) Django allows me to add to the query, but 
produces an SQL error.

Im Working on Python 3.6.5, Django 2.0.3 and Postgres 10

This problem is hardcore SQL ORM stuff so THX for anyone looking into this.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/816185ac-58eb-4f71-986c-04ac34e22e02%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to