Как преобразовать (и, возможно, оптимизировать) следующий необработанный запрос в Django Queryset
У меня есть следующий запрос:
SELECT OBJ_DESC_ERRORS.description, OBJ_DESC_ERRORS.object, OBJ_DESC_ERRORS.count_errors, OBJ_ERRORS.count_total FROM
(SELECT `metrics_event`.`description`, `metrics_event`.`object`, COUNT(`metrics_event`.`id`) AS `count_errors` FROM `metrics_event`
INNER JOIN `metrics_session` ON (`metrics_event`.`session_id` = `metrics_session`.`id`)
WHERE (`metrics_session`.`training_id` = 4 AND NOT (`metrics_session`.`completed_at` IS NULL) )
GROUP BY `metrics_event`.`description`, `metrics_event`.`object` ORDER BY `count_errors` DESC ) as OBJ_DESC_ERRORS
JOIN
(SELECT `metrics_event`.`object`, COUNT(`metrics_event`.`id`) AS `count_total` FROM `metrics_event`
INNER JOIN `metrics_session` ON (`metrics_event`.`session_id` = `metrics_session`.`id`)
WHERE (`metrics_session`.`training_id` = 4 AND NOT (`metrics_session`.`completed_at` IS NULL) )
GROUP BY `metrics_event`.`object` ORDER BY `count_total` DESC ) as OBJ_ERRORS
ON OBJ_DESC_ERRORS.object = OBJ_ERRORS.object
Как вы видите, я выполняю один и тот же запрос дважды. Причина в том, что мне нужно, чтобы count_errors разбивался по каждому агрегату object + description, но мне также нужно, чтобы count_total был только агрегатом по объекту. Это был способ, который я смог придумать. Теперь я хотел бы:
- How to write this using Django Queryset language ( I get stuck at the join/subquery parts)
- If there's a way to optimize this query (performance or clarity or both)
Надеюсь, я не обманываю, задавая 2 вопроса в одном. Мне показалось дубликатом создавать целое описание вопроса copy+paste для двух разных целей. Прошу прощения у админов, если это не так. В любом случае, я буду рад любой помощи по любому из этих двух вопросов.
Избавьтесь от внутренних ORDER BYs
; они не делают ничего полезного.
Перепишите запрос примерно так:
SELECT
me.description,
me.object,
SUM(...) AS count_errors,
SUM(...) AS count_total
FROM `metrics_event` AS me
INNER JOIN `metrics_session` AS ms ON (me.`session_id` = ms.`id`)
WHERE ms.`training_id` = 4
ms.`completed_at` IS NOT NULL
GROUP BY me.`description`, me.`object`
ORDER BY `count_total` DESC
Поскольку булево выражение оценивается как 1 для TRUE, иначе 0, придумайте аргумент для SUM()
, чтобы он был булевым выражением, которое обеспечивает желаемый COUNT.