sql—对连续的行序列进行分组

but5z9lq  于 2021-08-09  发布在  Java
关注(0)|答案(2)|浏览(391)

我正在尝试对sql server上布尔值为true的连续行进行分组。例如,一些源数据如下所示:

AccountID | ID | IsTrue | Date
-------------------------------
1         | 1  | 1      | 1/1/2013
1         | 2  | 1      | 1/2/2013
1         | 3  | 1      | 1/3/2013
1         | 4  | 0      | 1/4/2013
1         | 5  | 1      | 1/5/2013
1         | 6  | 0      | 1/6/2013
1         | 7  | 1      | 1/7/2013
1         | 8  | 1      | 1/8/2013
1         | 9  | 1      | 1/9/2013

这是我想要的输出

AccountID | Start    | End
-------------------------------
1         | 1/1/2013 | 1/3/2013
1         | 1/7/2013 | 1/9/2013

我有一个预感,有一些技巧与分组分区,将使这项工作,但我一直无法搞清楚。我在使用lag方面取得了一些进展,但还不能将其全部放在一起。
谢谢你的帮助!

czq61nw1

czq61nw11#

您可以尝试以下方法,这里是演示。我假设 id 将始终具有连续值。

with cte as
(
  select
    *,
    count(*) over (partition by IsTrue, rnk) as total
  from
  (
      select
          *,
          id - row_number() over (partition by IsTrue order by id, date) as rnk
      from myTable
  ) val
)

select
    accountId,
    min(date) as start,
    max(date) as end
from cte
where total > 1
group by
    accountId,
    rnk

输出:

| accountid | start      | end        |
| --------- | ---------- | -----------|
| 1         | 2013-01-01 | 2013-01-03 |
| 1         | 2013-01-07 | 2013-01-09 |
huus2vyu

huus2vyu2#

这是一个缺口和孤岛问题的例子。对于这个版本,您只需要为每个 isTrue . 对于相同的相邻值,从每个日期减去天数是一个常量:

select accountId, isTrue, min(date), max(date)
from (select t.*,
             row_number() over (partition by accountId, isTrue order by date) as seqnum
      from t
     ) t
group by accountId, isTrue, dateadd(day, -seqnum, date);

这定义了所有组。如果我假设您只需要大于1天的值“1”,那么:

select accountId, isTrue, min(date), max(date)
from (select t.*,
             row_number() over (partition by accountId, isTrue order by date) as seqnum
      from t
      where isTrue = 1
     ) t
group by accountId, isTrue, dateadd(day, -seqnum, date)
having count(*) > 1;

相关问题