Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 对于给定的子组,所有组的总功率是否相等?_Sql_Database_Postgresql_Aggregate - Fatal编程技术网

Sql 对于给定的子组,所有组的总功率是否相等?

Sql 对于给定的子组,所有组的总功率是否相等?,sql,database,postgresql,aggregate,Sql,Database,Postgresql,Aggregate,我有一个如下的PostgreSQL表: CREATE TABLE foo (man_id, subgroup, power, grp) AS VALUES ( 1, 'Sub_A', 1, 'Group_A' ), ( 2, 'Sub_B', -1, 'Group_A' ), ( 3, 'Sub_A', -1, 'Group_B' ), ( 4, 'Sub_B', 1, 'Group_B' ), ( 5, 'Sub_A', -1, 'Group_A'

我有一个如下的PostgreSQL表:

CREATE TABLE foo (man_id, subgroup, power, grp)
AS VALUES
    ( 1, 'Sub_A',  1, 'Group_A' ),
    ( 2, 'Sub_B', -1, 'Group_A' ),
    ( 3, 'Sub_A', -1, 'Group_B' ),
    ( 4, 'Sub_B',  1, 'Group_B' ),
    ( 5, 'Sub_A', -1, 'Group_A' ),
    ( 6, 'Sub_B',  1, 'Group_A' ),
    ( 7, 'Sub_A', -1, 'Group_B' ),
    ( 8, 'Sub_B',  1, 'Group_B' );
功率计算的工作原理如下:

CREATE TABLE foo (man_id, subgroup, power, grp)
AS VALUES
    ( 1, 'Sub_A',  1, 'Group_A' ),
    ( 2, 'Sub_B', -1, 'Group_A' ),
    ( 3, 'Sub_A', -1, 'Group_B' ),
    ( 4, 'Sub_B',  1, 'Group_B' ),
    ( 5, 'Sub_A', -1, 'Group_A' ),
    ( 6, 'Sub_B',  1, 'Group_A' ),
    ( 7, 'Sub_A', -1, 'Group_B' ),
    ( 8, 'Sub_B',  1, 'Group_B' );
grp组A中的子组Sub_A的总功率为(1+(-1))=0
grp组A中的子组Sub_B的总功率为(-1)+1)=0
grp组_B中的子组Sub_A的总功率为(-1)+(-1))=-2
grp组_B中的子组Sub_B的总功率为(1+1)=2

因此,组A中Sub_A的功率不等于组B中Sub_A的功率
所以A组中Sub_B的幂不等于B组中Sub_B的幂

我想用
子组
名称查询数据库。如果对于相同的
子组
名称幂在所有其他
grp
名称中相等,则它将返回
True
,否则返回
False

例如,
sub_A
sub_B
都将返回
False
。推荐的方法是什么

我想要像这样的东西:

SELECT * FROM foo (solution query will be added)
WHERE subgroup = 'sub_A'

它返回
False

假设在CREATE TABLE语句中,“sub_A”表示为“sub_A”(因为Postgres区分大小写),并且您的
power
值实际上是整数(如果不是,只需添加强制类型转换;没有它们,下面的代码更简单),然后,您可以按如下方式计算组中每个子组的功率:

select
    subgroup,
    grp,
    sum(power) as sum_power
from
    foo
group by
    subgroup,
    grp
select
    subgroup
from (
    select
        subgroup,
        grp,
        sum(power) as sum_power
    from
        foo
    group by
        subgroup,
        grp
    ) as subpwr
group by
    subgroup
having
    min(sum_power) = max(sum_power);
要确定子组的所有总功率值是否相同,只需检查最小值和最大值是否相同。将上一个查询转换为子查询,其中主查询执行该比较,如下所示:

select
    subgroup,
    grp,
    sum(power) as sum_power
from
    foo
group by
    subgroup,
    grp
select
    subgroup
from (
    select
        subgroup,
        grp,
        sum(power) as sum_power
    from
        foo
    group by
        subgroup,
        grp
    ) as subpwr
group by
    subgroup
having
    min(sum_power) = max(sum_power);
仔细阅读问题 我想用子组名称查询数据库

以及:

我想要像这样的东西

SELECT * FROM foo (solution query will be added)
WHERE subgroup = 'Sub_A'
性能的重要一点是尽早排除不相关的行,只计算给定子组的聚合。然后(假设不止几个不同的子组),
(子组)
上的索引可以帮助:

CREATE INDEX ON foo (subgroup);
如果给定子组中至少有两个组的总和不同,则以下每个查询都返回
FALSE
,在所有其他情况下返回
TRUE
(查询5的一个小例外,见下文)

问题1 问题2 问题3 问题4 这个很特别。相关答案及解释:

问题5 如果允许电源中的
NULL
值,则最后一个可能会失败。(但无论如何,在这种情况下,您必须定义预期结果。)

我运行了一个扩展测试,发现所有查询在理想条件下的执行情况大致相同:

dbfiddle

问题5往往比其他问题快一点。

这里有一个其他答案还没有提到的方法

SELECT SUM(power) = FIRST_VALUE(SUM(power)) OVER () powpow 
FROM foo
WHERE subgroup = 'Sub_A'
GROUP BY grp
ORDER BY powpow
LIMIT 1

-- returns:
-- false if some values differ
-- true if all values are the same
-- no rows if the where condition fails to match any rows.

请不要交叉发帖。我随意修改了一些与问题(或者我认为是这样)正交的、让人分心的拼写错误。请始终披露您的Postgres版本。大致有多少行、不同的组和子组?基数和值频率可能与选择最佳查询相关。如果子组
Sub_A
根本不存在,或者只存在一个组,您希望得到什么结果。我觉得选择不明确,因为人们可能希望
NULL
FALSE
TRUE
一如既往,您的答案是说明性的。我想知道您是否可以将我的解决方案与您测试过的5个备选方案进行比较。我很好奇,在这种设置下,避免子查询而使用窗口表达式和排序对性能有什么影响。@Haleemuli:我在测试电池中添加了:works,性能与其余的:dbfiddle差不多
SELECT min(total_power) = max(total_power)  -- can fail for NULL values
FROM  (
   SELECT sum(power) AS total_power
   FROM   foo
   WHERE  subgroup = 'Sub_A'
   GROUP  BY grp
   ) sub;
SELECT SUM(power) = FIRST_VALUE(SUM(power)) OVER () powpow 
FROM foo
WHERE subgroup = 'Sub_A'
GROUP BY grp
ORDER BY powpow
LIMIT 1

-- returns:
-- false if some values differ
-- true if all values are the same
-- no rows if the where condition fails to match any rows.