SQL子查询按列值获取行

时间:2018-06-26 22:51:45

标签: mysql sql postgresql aggregate

我有一个这样的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');

功率计算如下:

  • grp组_A中子组Sub_A的总功率为(4 + 5)= 9
  • grp Group_A中子组Sub_B的总功率为((-1)+1)= 0
  • grp组_B中子组Sub_A的总功率为((-1)+(-1))= -2
  • grp Group_B中子组Sub_B的总功率为(6 + 2)= 8

因此,Group_A中Sub_A的功率不等于Group_B中Sub_A的功率

因此,Group_A中Sub_B的功率不等于Group_B中Sub_B的功率

我想查询数据库并获取其中所有相同的subgroup名称在所有其他power中都不相同的情况下的行。

推荐的方法是什么?

我可以找到总功率的总和:

grp

MySQL解决方案也将被接受。

4 个答案:

答案 0 :(得分:0)

一种方法:

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)  -- can fail for NULL values;
   ) sg
JOIN foo f USING (subgroup);

在您的示例中,除最后一行带有'Sub_C'之外,所有行均符合条件。

与您先前的问题密切相关:

类似的解释和注意事项。

db <>提琴here

答案 1 :(得分:0)

我想表达您的问题的一种方法是,您希望合计一个组中子组的力量,然后找出具有相同名称的子组是否存在于另一个具有不同功效的组中。

第一步是合计所需的力量:

SELECT grp, subgroup, sum(power) as power
FROM foo
GROUP BY grp, subgroup

应该会给您类似的结果

grp      subgroup  power
-------  --------  -----
Group_A  Sub_A      9
Group_A  Sub_B      0
Group_B  Sub_A     -2
Group_B  Sub_B      8
Group_B  Sub_C      2

一旦有了,您就可以使用CTE将结果与自身连接起来,以进行比较以获得所需的结果。您无需指定是否要显示Sub_C,如果“不存在”被定义为具有“不同的总功效”,则需要使用左连接并检查别名{{1}中是否为空}。联接中的b使得每个差异仅在低阶组为grp1时出现一次。

<

答案 2 :(得分:0)

with totals as (
    select grp, subgroup, sum(power) as total_power
    from foo
    group by grp, subgroup
)
select * from totals t1
where t1.total_power <> all (
    select t2.total_power from totals t2
    where t2.subgroup = t.subgroup and t2.grp <> t1.grp
)

with totals as (
    select grp, subgroup, sum(power) as total_power
    from foo
    group by grp, subgroup
), matches as (
    select grp, subgroup, count(*) over (partition by subgroup, total_power) as matches
)
select * from counts where matches = 1;

答案 3 :(得分:0)

我将使用窗口功能:

select f.*
from (select f.*,
             min(sum_value)) over (partition by group) as min_sum_value,
             max(sum_value)) over (partition by group) as max_sum_value,
      from (select f.*,
                   sum(value) over (partition by subgroup, group) as sum_value
            from foo f
           ) f
      ) f
where min_sum_value <> max_sum_value;