Подзапрос SQL для извлечения строк по значениям столбцов - 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');

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

  • Общая мощность подгруппы Sub_A в группе Group_A составляет (4 + 5) = 9
  • Общая мощность подгруппы Sub_B в группе Group_A составляет ((-1) + 1) = 0
  • Общая мощность подгруппы Sub_A в группе GroupB: ((-1) + (-1)) = -2
  • Общая мощность подгруппы Sub_B в группе GroupB: (6 + 2) = 8

Таким образом, мощность Sub_A в Group_A не равна мощности Sub_A в Group_B

Таким образом, мощность Sub_B в Group_A не равна мощности Sub_B в Group_B

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

Какой рекомендуемый способ сделать это?

Я могу найти сумму полной мощности:

SELECT sum(power) AS total_power
FROM   foo
GROUP  BY grp

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

Ответы [ 4 ]

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

Я бы использовал оконные функции:

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;
0 голосов
/ 27 июня 2018

Я думаю, что способ сформулировать вашу проблему состоит в том, что вы хотите суммировать полномочия для подгруппы в группе, а затем выяснить, существует ли подгруппа с таким же именем в другой группе с другим полномочием.

Первый шаг состоит в суммировании сил, которые вы хотите:

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 появлялся, если «несуществующий» квалифицируется как имеющий «другую общую мощность», тогда вы захотите использовать левое соединение и проверить наличие нулей в псевдониме b. < в соединении делает так, что каждое различие появляется только один раз с группой более низкого порядка как grp1.

WITH totals AS (
    SELECT grp, subgroup, sum(power) as power
    FROM foo
    GROUP BY grp, subgroup
    ORDER BY grp, subgroup
)
SELECT a.subgroup,
       a.grp as grp1, a.power as Power1,
       b.grp as grp2, b.power as Power2
FROM totals a
    INNER JOIN totals b ON b.subgroup = a.subgroup
                           and a.grp < b.grp
WHERE b.power <> a.power
ORDER BY a.subgroup, a.grp, b.grp 
0 голосов
/ 27 июня 2018
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;
0 голосов
/ 27 июня 2018

В одну сторону:

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.

тесно связана с вашим предыдущим вопросом:

Аналогичные объяснения и соображения.

дБ <> скрипка здесь

...