Сбалансировать значения с помощью SQL в PostgreSQL - PullRequest
0 голосов
/ 27 июня 2018

Моя таблица Postgresql выглядит,

CREATE TABLE foo(man_id, subgroup, power, grp)
AS VALUES
    (1, 'Sub_A',  4, 'Group_A'),
    (2, 'Sub_B', -1, 'Group_A'),
    (3, 'Sub_A', -1, 'Group_B'),
    (4, 'Sub_B',  6, 'Group_B'),
    (5, 'Sub_A',  5, 'Group_A'),
    (6, 'Sub_B',  1, 'Group_A'),
    (7, 'Sub_A', -1, 'Group_B'),
    (8, 'Sub_B',  2, 'Group_B'),
    (9, 'Sub_C',  2, 'Group_B');

Расчет мощности работает следующим образом:

Total Power of Subgroup Sub_A in the grp Group_A is (4 + 5 ) = 9
Total Power of Subgroup Sub_B in the grp Group_A is ((-1) + 1 ) = 0
Total Power of Subgroup Sub_A in the grp Group_B is ((-1) + (-1) ) = -2
Total Power of Subgroup Sub_B in the grp Group_B is (6 + 2 ) = 8
So the power of Sub_A in the Group_A is not equal to power of Sub_A in the Group_B

So the power of Sub_B in the Group_A is not equal to power of Sub_B in the Group_B

Я могу запросить базу данных и извлечь данные, если для одного и того же subgroup общее имя power не равно для всех других grp имен.

SELECT f.*
FROM  (
   SELECT subgroup
   FROM  (
      SELECT subgroup, grp, sum(power) AS total_power
      FROM   foo
      GROUP  BY subgroup, grp
      ) sub
   GROUP  BY 1
   HAVING min(total_power) <> max(total_power)
   ) sg
JOIN foo f USING (subgroup);

Я также хочу сделать значение суммы идентичным. Для одного и того же subgroup общее имя power должно быть одинаковым для всех остальных grp имен.

Мы можем получить записи, в которых сумма не равна вышеприведенному запросу. Затем мы можем найти разницу в значении sum(power) и добавить это значение разницы в power любого subgroup, где power меньше, чем конкретный grp.

Будет также принято решение MySQL.

Приведенный выше запрос вернет эти данные, потому что для одного и того же subgroup total power не равно для grp s,

(1, 'Sub_A',  4, 'Group_A')
(5, 'Sub_A',  5, 'Group_A')
(3, 'Sub_A', -1, 'Group_B')
(7, 'Sub_A', -1, 'Group_B')
(2, 'Sub_B', -1, 'Group_A')
(6, 'Sub_B',  1, 'Group_A')
(4, 'Sub_B',  6, 'Group_B')
(8, 'Sub_B',  2, 'Group_B')

Теперь я хочу изменить значения мощности, чтобы сделать сумму идентичной,

Например, для Sub_A общая разность мощности между Group_A и Group_B равна (9 - (- 1-1)) = 11, поэтому мы добавим 11 к любому значению мощности Sub_A в Group_B, скажем, мы изменим это запись,

(3, 'Sub_A', -1, 'Group_B') преобразовано в (3, 'Sub_A', 10, 'Group_B')

То же самое мы сделаем и для других, где бы они не находились.

1 Ответ

0 голосов
/ 27 июня 2018

Ниже запрос даст желаемый результат

  with foo(man_id, subgroup, power, grp) as (
    select * from
    (
    VALUES
    (1, 'Sub_A',  4, 'Group_A'),
    (2, 'Sub_B', -1, 'Group_A'),
    (3, 'Sub_A', -1, 'Group_B'),
    (4, 'Sub_B',  6, 'Group_B'),
    (5, 'Sub_A',  5, 'Group_A'),
    (6, 'Sub_B',  1, 'Group_A'),
    (7, 'Sub_A', -1, 'Group_B'),
    (8, 'Sub_B',  2, 'Group_B'),
    (9, 'Sub_C',  2, 'Group_B')
    ) as x(man_id, subgroup, power, grp)
), sub_per_group as (
  select
    subgroup,
    grp,
    sum(power) tot_per_grp
  from foo
  group by subgroup,grp
), sub_calc as (
select
  subgroup,
  max(tot_per_grp) as max,
  json_agg(
    json_build_object(
        'grp',grp,
        'tot_per_grp',tot_per_grp
    )
  ) as grps_tot
from sub_per_group
group by subgroup
having count(distinct tot_per_grp)!=1
)
select f.man_id,f.subgroup,
  case
      when rn=1 then
      (
        power+
        (
         coalesce(max,0)-
         coalesce((
           select (v->>'tot_per_grp')::int
            from
          json_array_elements(grps_tot) as v where (v->>'grp')::text =f.grp),0)
        )
      )
    else
     power
  end,
  f.grp
from sub_calc sc
right join (
  select
    row_number() over(partition by subgroup,grp) as rn,
    foo.*
  from foo
) f on f.subgroup=sc.subgroup and f.rn=1
order by subgroup,grp
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...