我有一个包含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
降序排列。
想象一下,所有这些行都是事务。当标志为1时,我们有一个检查点。因此,例如从第20行到第17行是一个期间(始终从旧到新计数)。从第17行到第12行是另一个句点,依此类推。
请注意,在第9、8和7行中,我们有3个连续的标志,其值为1
。发生这种情况时,连续的1不带0,我想将所有连续的1视为一个组。我希望它们以总金额显示为一行并保留其中MIN(Created)
。
例如,对于第9-7行,我要将其分组为amount
的值为151.2
,flag
的值为1
和{ {1}}的值为Created
(三行中的2019-07-23 00:00:00.000
。
此表的示例输出如下。
min(date)
答案 0 :(得分:1)
如果只想折叠相邻的“ 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;
答案 1 :(得分:0)
您希望聚合所有标记为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);