SQL Server-通过标志汇总日期
我使用的是SQL Server 2008(如果需要,我可以访问SQL 2017),并且有一个如下表:SQL Server-通过标志汇总日期,sql,sql-server,tsql,gaps-and-islands,Sql,Sql Server,Tsql,Gaps And Islands,我使用的是SQL Server 2008(如果需要,我可以访问SQL 2017),并且有一个如下表: DECLARE @tbl TABLE (recdate DATE, myflag BIT) 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.
DECLARE @tbl TABLE (recdate DATE, myflag BIT)
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.
该表包含一个范围内所有日期的行,myflag位将更改为关闭和打开,类似于以下内容:
DECLARE @tbl TABLE (recdate DATE, myflag BIT)
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.
但我真正需要的是
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更改时,它都会创建一个新行,并且前一行设置了结束日期(如果有意义的话)
我确信有一个非常明显的方法可以做到这一点,但我已经准备好把头撞到墙上了。。我在选择、子选择、插入和更新临时表中来回进行,甚至尝试使用游标(我知道!但这是一次性查询)这是一个空白和孤岛问题。为此,您可以使用不同的行号:
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;
用语言来解释这一点有点棘手。我发现,如果您运行子查询,您将看到为什么要查找的组的差异是恒定的
如果您的日期是连续的,没有间隔、重复或时间成分,您可以执行稍微简单一点的操作:
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;
这与第一个版本的逻辑基本相同。查看超前和滞后。但你必须在2008年之后才能继续前进,因为它直到2012年才推出。谢谢肖恩-我在下面有一个答案,但我一定会检查一下,这样我就有希望在前进中学到一些有用的东西!我添加了gaps和islands标签。这是一个有趣的领域,因为有各种各样的方法,你可能必须尝试几种适合的方法(如这里所示!)。我不知道为什么这会奏效,但我肯定会读一些关于它的文章,因为它似乎可以在将来帮我省去很多麻烦。在我尝试过的测试用例中,这种方法对我很有效。。非常感谢。只要允许,我会尽快标记答案