【问题标题】:Aggregate only Sequential values仅聚合顺序值
【发布时间】:2019-10-21 10:51:00
【问题描述】:

我有一个有 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.2flag 的值为 1Created 的值为 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

【问题讨论】:

  • 您的示例输出看起来很像输入。
  • MySQL SQL Server 和 MySQL 不使用 T-SQL。我已经删除了冲突的标签;请重新标记您真正使用的 RDBMS。至于你的帖子,你的问题是什么,你似乎没有问过。您尝试过什么方法来解决问题,为什么没有成功?
  • 问题是我想达到我所展示的解决方案,但我不知道执行此操作的代码。我需要帮助!
  • “我需要帮助!”我们仍然需要首先知道您真正使用的是什么 RDBMS。
  • "请注意,在第 9,8 和 7 行中,我们有 3 个连续的标志,其值为 1。当这种情况发生时,连续的 1 没有 0,我想处理所有连续的1s 作为一个组。我希望它们显示为一行,总金额并保持它们的 MIN(Created)。" 如果该组中的最小日期具有相同日期两次或多次的关系?那么你有一个问题,因为除了 Created 之外你没有订单..

标签: sql sql-server sql-server-2017 gaps-and-islands


【解决方案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;

当我们包含0s 时,这并不完全有效,因为0s 将与1s 组合在一起。所以我觉得最简单的方法是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;

【讨论】:

  • @PoNti3 评论的位置有误,但我阅读了它并将 SQL Server 标记添加到问题中......
【解决方案2】:

您想要聚合标记为 1 的所有连续行。您可以通过标记为 0 的行的运行计数来实现此目的。您可以在下表中看到该标志 + 运行的零计数标识组。

创建 |金额 |旗帜 | COUNT_0 ------------+--------+------+-------- 2019-12-01 | 50,40 | 1 | 0 \ 两行 flag=1, count_0=0 => 一组 2019-11-21 | 50,40 | 1 | 0 / 2019-11-06 | 50,40 | 0 | 1 > 唯一行 flag=0, count_0=1 => 一组 2019-10-04 | 50,40 | 1 | 1 \ 两行 flag=1, count_0=1 => 一组 2019-09-08 | 50,40 | 1 | 1 / 2019-09-01 | 50,40 | 0 | 2 > 唯一行 flag=0, count_0=2 => 一组 2019-08-04 | 50,40 | 1 | 2\ 2019-07-24 | 50,40 | 1 | 2 |所有三行 flag=1, count_0=2 => 一组 2019-07-23 | 50,40 | 1 | 2 / 2019-06-01 | 50,40 | 0 | 3 > 唯一行 flag=0, count_0=3 => 一组 2019-05-05 | 50,40 | 0 | 4 > 唯一行 flag=0, count_0=4 => 一组 2019-04-25 | 50,40 | 1 | 4 > 唯一行 flag=1, count_0=4 => 一组 2019-03-11 | 50,40 | 0 | 5 > 唯一行 flag=0, count_0=5 => 一组 2019-02-03 | 50,40 | 0 | 6 > 唯一行 flag=0, count_0=6 => 一组 2019-02-02 | 50,40 | 0 | 7 > 唯一行 flag=0, count_0=7 => 一组 2019-02-01 | 50,40 | 0 | 8 > 唯一行 flag=0, count_0=8 => 一组 2019-01-31 | 50,40 | 1 | 8 > 唯一行 flag=1, count_0=8 => 一组 2019-01-26 | 50,40 | 0 | 9 > 唯一行 flag=0, count_0=9 => 一组 2019-01-26 | 50,40 | 0 | 10 > 唯一行 flag=0, count_0=10 => 一组 2019-01-01 | 50,40 | 1 | 10 > 唯一行 flag=1, count_0=10 => 一组

相关查询:

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);

【讨论】:

    猜你喜欢
    • 2011-12-22
    • 2021-04-13
    • 1970-01-01
    • 2016-03-20
    • 2020-07-30
    • 2014-05-25
    • 2017-01-24
    • 2018-11-28
    • 2015-06-19
    相关资源
    最近更新 更多