Агрегировать только последовательные значения - PullRequest
0 голосов
/ 21 октября 2019

У меня есть таблица с 3 столбцами

  Create table test 
(
        Created  Datetime
    ,   Flag     Bit 
    ,   Amount   Money
)

, которая выглядит следующим образом

      Created              Flag    Amount
2019-12-01 00:00:00.000    1        50,40
2019-11-21 00:00:00.000    1        50,40
2019-11-06 00:00:00.000    0        50,40
2019-10-04 00:00:00.000    1        50,40
2019-09-08 00:00:00.000    1        50,40
2019-09-01 00:00:00.000    0        50,40
2019-08-04 00:00:00.000    1        50,40
2019-07-24 00:00:00.000    1        50,40
2019-07-23 00:00:00.000    1        50,40
2019-06-01 00:00:00.000    0        50,40
2019-05-05 00:00:00.000    0        50,40
2019-04-25 00:00:00.000    1        50,40
2019-03-11 00:00:00.000    0        50,40
2019-02-03 00:00:00.000    0        50,40
2019-02-02 00:00:00.000    0        50,40
2019-02-01 00:00:00.000    0        50,40
2019-01-31 00:00:00.000    1        50,40
2019-01-26 00:00:00.000    0        50,40
2019-01-26 00:00:00.000    0        50,40
2019-01-01 00:00:00.000    1        50,40

Как вы можете видеть, она упорядочена по Created в порядке убывания.

Представьте, что все эти строки являются Транзакциями. Когда флаг один, у нас есть контрольная точка. Так, например, от строки 20 до 17 - один период (всегда считая от старшего к новому). От строки 17 до 12 - другой период и т. Д.

Обратите внимание, что в строках 9,8 и 7 у нас есть 3 последовательных флага со значением 1. Когда это происходит, имея последовательные 1 с без 0, я хочу рассматривать все последовательные 1 как группу. Я хочу, чтобы они отображались в виде одной строки с Суммированной суммой и сохраняя их MIN(Created).

Например, для строк 9-7 я хочу сгруппировать их в одну строку, где amount имеет значение151.2, flag значение 1 и Created значение 2019-07-23 00:00:00.000 (min(date) из трех строк.

Пример вывода этой таблицы будет следующим.

Created                   Flag  Amount
2019-11-21 00:00:00.000   1     100,80
2019-11-06 00:00:00.000   0     50,40
2019-09-08 00:00:00.000   1     100,80
2019-09-01 00:00:00.000   0     50,40
2019-07-23 00:00:00.000   1     151,20
2019-06-01 00:00:00.000   0     50,40
2019-05-05 00:00:00.000   0     50,40
2019-04-25 00:00:00.000   1     50,40
2019-03-11 00:00:00.000   0     50,40
2019-02-03 00:00:00.000   0     50,40
2019-02-02 00:00:00.000   0     50,40
2019-02-01 00:00:00.000   0     50,40
2019-01-31 00:00:00.000   1     50,40
2019-01-26 00:00:00.000   0     50,40
2019-01-26 00:00:00.000   0     50,40
2019-01-01 00:00:00.000   1     50,40

Ответы [ 2 ]

1 голос
/ 21 октября 2019

Если вы просто хотите свернуть соседние «1», то один из подходов заключается в назначении группировки на основе количества предшествующих 0 и агрегирования. Таким образом, для агрегации "1":

select min(created), 1 as flag, sum(amount)
from (select t.*,
             sum(1 - flag) over (order by created) as grouping
      from t
     ) t
where flag = 1
group by grouping;

Это не совсем работает, когда мы включаем 0 с, потому что 0 с будет объединено с 1 с. Поэтому я думаю, что самый простой метод - это union all:

select min(created), 1 as flag, sum(amount)
from (select t.*,
             sum(1 - flag) over (order by created) as grouping
      from t
     ) t
where flag = 1
group by grouping
union all
select created, flag, amount
from t
where flag = 0;

. Первоначально я неверно истолковал вопрос как запрос сводки по всем периодам, а не только по соседним «1». Вы можете сделать это с накопленной суммой, чтобы идентифицировать группы:

select t.*,
       sum(flag) over (order by created) as grouping
from t;

И затем использовать подзапрос для агрегирования этого:

select min(created), max(created), count(*) as num_transactions,
       sum(amount) as total_amount
from (select t.*,
             sum(flag) over (order by created) as grouping
      from t
     ) t
group by grouping;
0 голосов
/ 21 октября 2019

Вы хотите объединить все последовательные строки, помеченные 1. Вы можете добиться этого с помощью текущего количества строк, помеченных 0. В таблице ниже вы можете видеть, что флаг + текущее число нулей идентифицирует группы.

Created    | Amount | Flag | COUNT_0
-----------+--------+------+--------
2019-12-01 | 50,40  | 1    |       0   \   both rows flag=1, count_0=0 => one group
2019-11-21 | 50,40  | 1    |       0   /
2019-11-06 | 50,40  | 0    |       1   >   the only row with flag=0, count_0=1 => one group
2019-10-04 | 50,40  | 1    |       1   \   both rows flag=1, count_0=1 => one group
2019-09-08 | 50,40  | 1    |       1   /
2019-09-01 | 50,40  | 0    |       2   >   the only row with flag=0, count_0=2 => one group
2019-08-04 | 50,40  | 1    |       2   \
2019-07-24 | 50,40  | 1    |       2    |  all three rows flag=1, count_0=2 => one group
2019-07-23 | 50,40  | 1    |       2   /
2019-06-01 | 50,40  | 0    |       3   >   the only row with flag=0, count_0=3 => one group
2019-05-05 | 50,40  | 0    |       4   >   the only row with flag=0, count_0=4 => one group
2019-04-25 | 50,40  | 1    |       4   >   the only row with flag=1, count_0=4 => one group
2019-03-11 | 50,40  | 0    |       5   >   the only row with flag=0, count_0=5 => one group
2019-02-03 | 50,40  | 0    |       6   >   the only row with flag=0, count_0=6 => one group
2019-02-02 | 50,40  | 0    |       7   >   the only row with flag=0, count_0=7 => one group
2019-02-01 | 50,40  | 0    |       8   >   the only row with flag=0, count_0=8 => one group
2019-01-31 | 50,40  | 1    |       8   >   the only row with flag=1, count_0=8 => one group
2019-01-26 | 50,40  | 0    |       9   >   the only row with flag=0, count_0=9 => one group
2019-01-26 | 50,40  | 0    |      10   >   the only row with flag=0, count_0=10 => one group
2019-01-01 | 50,40  | 1    |      10   >   the only row with flag=1, count_0=10 => one group

Соответствующий запрос:

select min(created), min(flag), sum(amount)
from
(
  select
    m.*,
    count(case when flag = 0 then 1 end) over (order by created) as count_0
  from mytable m
)
group by flag, count_0
order by min(created);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...