У нас есть данные, поступающие в следующей структуре
entity_id entity_value category_id category_weight group_id group_weight
1 100 11 6 101 4
1 100 11 6 102 3
1 100 12 5 102 3
1 100 12 5 103 2
1 100 13 6 101 4
Сущность может принадлежать к любой категории и к любой группе в любой комбинации, не существует явной связи между членством в категории и членством в группе.
Данные избыточны, но непротиворечивы; если в одной строке указано, что вес категории 11 равен 6, во всех строках будет указано, что вес категории 11 равен 6. То же самое относится к группам и их весам.
Строка данных однозначно идентифицируется как {entity_id, category_id, group_id}
.
1011 *
*
Цель состоит в том, чтобы распределить значение сущности по всем строкам на основе различных весов. Сначала распределение по категориям, затем распределение по группам.
Шаг 1: Распределение по категориям
Объект 1 связан с 3 категориями {11, 12, 13} с весами {6, 5, 4}
Назначить 100 * (6 / (6 + 5 + 6)) для категории 11 => 35,29
Назначьте 100 * (5 / (6 + 5 + 6)) для категории 12 => 29,41
Назначьте 100 * (6 / (6 + 5 + 6)) для категории 13 => 35,29
Шаг 2: Распределить результаты по группам
Entity1Category11 связан с группами {101, 102} с весами {4, 3}
Назначить 35,29 * (4 / (4 + 3)) группе 101 => 20,17
Назначить 35,29 * (3 / (4 + 3)) группе 102 => 15,12
Entity1Category12 связан с группами {102, 103} с весами {3, 2}
Назначить 29,41 * (3 / (3 + 2)) группе 102 => 17,65
Назначить 29,41 * (2 / (3 + 2)) группе 103 => 11,76
Entity1Category13 связан с группами {101} с весами {4}
Назначить 35,29 * (4 / (4)) группе 103 => 35,29
Второй шаг я могу сделать с оконными функциями. Красиво и аккуратно, я не присоединяюсь.
Однако для первого шага требуются подзапросы и самостоятельное соединение.
Например ... http://sqlfiddle.com/#!18/be890/1
SELECT
sample.entity_id,
sample.category_id,
sample.group_id,
sample.entity_value AS original_value,
sample.entity_value
* (sample.category_weight / entity.total_category_weight)
* (sample.group_weight / SUM(sample.group_weight) OVER (PARTITION BY sample.entity_id, sample.category_id))
AS apportioned_value
FROM
(
SELECT
entity_id,
SUM(category_weight) AS total_category_weight
FROM
(
SELECT
entity_id,
category_id,
MAX(category_weight) AS category_weight
FROM
sample
GROUP BY
entity_id,
category_id
)
entity_category
GROUP BY
entity_id
)
entity
INNER JOIN
sample
ON sample.entity_id = entity.entity_id
Есть ли более аккуратный способ, без необходимости самостоятельного присоединения?