Академическая головоломка: производные пропорции без самостоятельного объединения - PullRequest
0 голосов
/ 09 мая 2018

У нас есть данные, поступающие в следующей структуре

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

Есть ли более аккуратный способ, без необходимости самостоятельного присоединения?

1 Ответ

0 голосов
/ 04 сентября 2018
SELECT
  entity_id,
  category_id,
  group_id,
  entity_value   AS original_value,
  entity_value
  * (category_weight / SUM(scaled_cat_weight) OVER (PARTITION BY entity_id             ))
  * (group_weight    / SUM(group_weight     ) OVER (PARTITION BY entity_id, category_id))
    AS apportioned_value
FROM
(
  SELECT
    *,
    category_weight / COUNT(*) OVER (PARTITION BY entity_id, category_id)   AS scaled_cat_weight
  FROM
    sample
)
  scaled
ORDER BY
  entity_id,
  category_id,
  group_id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...