PostgreSql: оптимизация для расчета процента от суммы подгруппы к общей сумме - PullRequest
0 голосов
/ 29 апреля 2020

Я написал запрос для расчета общей суммы и суммы всех рискованных = 1 с во время окна. Этот запрос занимает около 800 мс только для записей 40 КБ, есть способ улучшить приведенный ниже запрос.

Здесь я пытаюсь добиться того, чтобы вычислить сумму СУММ и СУММ риска для заданного времени окна, так что я может вычислить процент рискованных элементов за заданное время окна

SELECT
    e.entity_uuid AS "entityUuid",
    SUM(e.count) AS "totalSum",
    tvc.tvcsum AS "totalRiskySum",
    ROUND(tvc.tvcsum * 1.0 / SUM(e.count) * 100, 2)::FLOAT AS "percentage"
    FROM address_entity e
LEFT JOIN (
    SELECT
    e.entity_uuid,
    SUM(e.count) AS "tvcsum"
    FROM address_entity e
    WHERE e.depth = 1
      AND e.monitoring_report_id IN (
        SELECT m.id FROM monitoring_report m
                WHERE m.report_date BETWEEN '2020-03-01' AND '2020-03-29'
      )
      AND e.entity_uuid IN ('393996d1-8df4-414f-8534-bd96f49ce16d','b6497c14-4264-4054-abd3-cb8594fb5072','c2fd62b3-47b3-4fd9-a4ff-a9cf847cd134','e9fa9758-e856-4ce1-9a3a-d0d4b0c35977','5dd4b3b6-cebd-4ce6-93fd-6e59ba8420e7','10d31034-2725-4ac5-937e-4b84e90e3be9')
      AND e.category IN ( SELECT category_uuid FROM wiki_entity WHERE risky = 1 GROUP BY category_uuid)
    GROUP BY e.entity_uuid
) tvc ON tvc.entity_uuid = e.entity_uuid
    WHERE e.depth = 1
      AND e.monitoring_report_id IN (
        SELECT m.id FROM monitoring_report m
                WHERE m.report_date BETWEEN '2020-03-01' AND '2020-03-29'
      )
      AND e.entity_uuid IN ('393996d1-8df4-414f-8534-bd96f49ce16d','b6497c14-4264-4054-abd3-cb8594fb5072','c2fd62b3-47b3-4fd9-a4ff-a9cf847cd134','e9fa9758-e856-4ce1-9a3a-d0d4b0c35977','5dd4b3b6-cebd-4ce6-93fd-6e59ba8420e7','10d31034-2725-4ac5-937e-4b84e90e3be9')
    GROUP BY e.entity_uuid, tvc.tvcsum

Что этот запрос SQL делает?:

ВЫБОР И ВЛЕВО ОБЪЕДИНЯЮТ оба запрашивают одну и ту же таблицу с одинаковым набором фильтров ( в предложении WHERE) единственное отличие состоит в том, что LEFT JOIN добавляет дополнительный фильтр, ограничивающий выбор строк с risky = 1, где в качестве внешнего выбираются все строки.

Таким образом, мы получаем общую сумму в первом выборе, а также получаем risky = 1 в LEFT JOIN теперь мы можем легко вычислить процент риска для данного временного диапазона как AND e.monitoring_report_id IN ( SELECT m.id FROM monitoring_report m WHERE m.report_date BETWEEN '2020-03-01' AND '2020-03-29' )

Вывод запроса:

enter image description here

...