首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >SQL Server -按标志汇总日期

SQL Server -按标志汇总日期
EN

Stack Overflow用户
提问于 2018-06-06 05:04:46
回答 1查看 41关注 0票数 3

我使用的是SQL Server 2008 (如果需要,可以访问SQL 2017 ),并且有一个如下所示的表:

代码语言:javascript
复制
DECLARE @tbl TABLE (recdate DATE, myflag BIT)

该表包含一个范围内所有日期的行,myflag位将时断时续地变化,如下所示:

代码语言:javascript
复制
recdate    | myflag
2017-01-01 | 1
2017-01-02 | 1
2017-01-03 | 1
...
2017-04-03 | 1
2017-04-04 | 0
2017-04-05 | 0
..
2017-05-15 | 0
2017-05-16 | 1
etc.

但我真正需要的是像这样

代码语言:javascript
复制
period_from | period_to  | myflag
2017-01-01  | 2017-04-03 | 1
2017-04-04  | 2017-05-15 | 0
2017-05-16  | 2017-05-21 | 1

因此,每次myflag更改时,它都会创建一个新行,并且前一行设置了结束日期(如果有意义的话)

我相信有一种非常明显的方法可以做到这一点,但是我已经准备好用头撞墙了.我在临时表中反复使用selects、subselects、inserts和updates,甚至尝试使用游标(我知道!但这是一次性查询)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-06 05:08:06

这是一个缝隙和岛屿问题。为此,您可以使用行号的不同:

代码语言:javascript
复制
select min(recdate) as period_from, max(recdate) as period_to, flag
from (select t.*,
             row_number() over (order by recdate) as seqnum,
             row_number() over (partition by flag order by recdate) as seqnum_f
      from @tbl t
     ) t
group by (seqnum - seqnum_f), flag;

为什么这样做有点难以用语言来解释。我发现,如果运行子查询,就会发现为什么要查找的组的差异是恒定的。

如果你的日期是连续的,没有间隔,没有重复,也没有时间成分,你可以做稍微简单一点的:

代码语言:javascript
复制
select min(recdate) as period_from, max(recdate) as period_to, flag
from (select t.*,
             dateadd(day, 
                     - row_number() over (partition by flag order by recdate
                     recdate
                    ) as grp
      from @tbl t
     ) t
group by grp, flag;

这基本上与第一个版本的逻辑相同。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50708900

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档