#34978: Annotating through an aggregate with MySQL/MariaDB raises 1056 "Can't 
group
on" error
-------------------------------------+-------------------------------------
               Reporter:  Matthew    |          Owner:  nobody
  Somerville                         |
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  4.2
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 I have some code I am trying to update from Django 3.2 to 4.2, using
 MariaDB, that has worked in previous Django versions, and works fine in
 4.1, but fails in 4.2. You can see an example GitHub Action output at
 https://github.com/dracos/Theatricalia/actions/runs/6922955832 showing 3
 and 4.1 passing, but 4.2 failing.

 One problem query is the following code:
 {{{
     seen =
 
user.visit_set.annotate(min_press_date=Min('production__place__press_date')).annotate(best_date=RawSQL('MIN(IFNULL(productions_place.press_date,
 IF(productions_place.end_date!="", productions_place.end_date,
 productions_place.start_date)))', ())).order_by('-best_date')
 }}}

 In Django 4.1, this produces the following SQL, which works fine:
 {{{
 SELECT `productions_visit`.`id`, `productions_visit`.`production_id`,
 `productions_visit`.`user_id`, `productions_visit`.`recommend`,
 `productions_visit`.`date`, MIN(`productions_place`.`press_date`) AS
 `min_press_date`, (MIN(IFNULL(productions_place.press_date,
 IF(productions_place.end_date!="", productions_place.end_date,
 productions_place.start_date)))) AS `best_date` FROM `productions_visit`
 INNER JOIN `productions_production` ON
 (`productions_visit`.`production_id` = `productions_production`.`id`) LEFT
 OUTER JOIN `productions_place` ON (`productions_production`.`id` =
 `productions_place`.`production_id`) WHERE `productions_visit`.`user_id` =
 1 GROUP BY `productions_visit`.`id` ORDER BY `best_date` DESC
 }}}

 Whilst the SQL produced by Django 4.2 is:
 {{{
 SELECT `productions_visit`.`id`, `productions_visit`.`production_id`,
 `productions_visit`.`user_id`, `productions_visit`.`recommend`,
 `productions_visit`.`date`, MIN(`productions_place`.`press_date`) AS
 `min_press_date`, (MIN(IFNULL(productions_place.press_date,
 IF(productions_place.end_date!="", productions_place.end_date,
 productions_place.start_date)))) AS `best_date` FROM `productions_visit`
 INNER JOIN `productions_production` ON
 (`productions_visit`.`production_id` = `productions_production`.`id`) LEFT
 OUTER JOIN `productions_place` ON (`productions_production`.`id` =
 `productions_place`.`production_id`) WHERE `productions_visit`.`user_id` =
 1 GROUP BY `productions_visit`.`id`, 7 ORDER BY 7 DESC LIMIT 21
 }}}

 It has added a group by on column 7 (which is best_date) and this then
 gives a "1056 Can't group by best_date" error from MySQL/MariaDB.

 I have bisected Django between 4.1 and 4.2, and the problem was introduced
 by the fix for #31331 in 041551d716b69ee7c81199eee86a2d10a72e15ab. Somehow
 that fix means my annotation is now being included in the group by when it
 shouldn't be, as it's an aggregate per visit ID, as far as I understand.
 Let me know if you need any other details.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34978>
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/0107018be988fc7b-7fc7083d-c974-483c-8ba7-26455e3e1814-000000%40eu-central-1.amazonses.com.

Reply via email to