Сбалансировать значения с помощью SQL в PostgreSQL

0

Моя таблица 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 общая 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')

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

  • 0
    Можете ли вы дать нам желаемый набор результатов
  • 0
    Я обновил вопрос. Можете ли вы проверить.
Теги:

1 ответ

0
Лучший ответ

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

  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
  • 0
    Блестящий ответ.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню