在PostgreSQL中使用SQL平衡值

时间:2018-06-27 08:42:03

标签: mysql sql postgresql

我的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的{​​{1}}的{​​{1}}中,其中subgroup在该特定power下较小。 / p>

MySQL解决方案也将被接受。

上面的查询将返回此数据,因为对于相同的grp总计subgroup不等于power秒,

grp

现在,我想修改幂的值以使总和相同,

作为示例,对于Group_A和Group_B之间的Sub_A总功率差为(9-(-1-1))= 11,因此我们将11添加到Group_B下的任何Sub_A功率值中,假设我们修改了此值记录,

(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') 转换为(3, 'Sub_A', -1, 'Group_B')

在不平衡的地方,我们也会为他人做同样的事情。

1 个答案:

答案 0 :(得分: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