Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server-通过标志汇总日期_Sql_Sql Server_Tsql_Gaps And Islands - Fatal编程技术网

SQL Server-通过标志汇总日期

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.

我使用的是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.
该表包含一个范围内所有日期的行,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标签。这是一个有趣的领域,因为有各种各样的方法,你可能必须尝试几种适合的方法(如这里所示!)。我不知道为什么这会奏效,但我肯定会读一些关于它的文章,因为它似乎可以在将来帮我省去很多麻烦。在我尝试过的测试用例中,这种方法对我很有效。。非常感谢。只要允许,我会尽快标记答案